use std::io::Write;
use std::process::{Command, Output, Stdio};

fn run_cli(args: &[&str], input: &[u8]) -> Output {
    let mut child = Command::new(env!("CARGO_BIN_EXE_agent-desktop"))
        .args(args)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .expect("CLI starts");
    child
        .stdin
        .take()
        .expect("stdin is piped")
        .write_all(input)
        .expect("stdin accepts input");
    child.wait_with_output().expect("CLI exits")
}

#[test]
fn each_stdin_command_rejects_invalid_utf8_before_dispatch() {
    let input = b"private-marker\xff";
    for args in [
        vec!["type", "@s8f3k2p9:e1", "--stdin"],
        vec!["set-value", "@s8f3k2p9:e1", "--stdin"],
        vec!["clipboard-set", "--stdin"],
    ] {
        let output = run_cli(&args, input);
        let response: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
        assert!(!output.status.success());
        assert_eq!(response["command"], args[0]);
        assert_eq!(response["ok"], false);
        assert_eq!(response["error"]["code"], "INVALID_ARGS");
        assert!(
            response["error"]["message"]
                .as_str()
                .unwrap()
                .contains("valid UTF-8")
        );
        assert!(!String::from_utf8_lossy(&output.stdout).contains("private-marker"));
        assert!(!String::from_utf8_lossy(&output.stderr).contains("private-marker"));
    }
}