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

const EXIT_USAGE: i32 = 2;

fn run(args: &[&str]) -> Output {
    Command::new(env!("CARGO_BIN_EXE_webrtc-test"))
        .args(args)
        .env_remove("GRID_FIRST_NAME")
        .env_remove("GRID_LAST_NAME")
        .env_remove("GRID_PASSWORD")
        .env_remove("GRID_LOGIN_URL")
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .expect("run webrtc-test")
}

fn text(bytes: &[u8]) -> &str {
    std::str::from_utf8(bytes).expect("UTF-8 process output")
}

#[test]
fn help_documents_native_prerequisites_fake_flow_and_live_gates() {
    let output = run(&["--help"]);
    assert!(output.status.success());
    let help = text(&output.stdout);
    for marker in [
        "--fake",
        "--list-devices",
        "--allow-live-login",
        "--confirm-live-login",
        "--allow-session-audio",
        "--input-device",
        "--output-device",
        "--wav",
        "ICE/DTLS/SRTP/SCTP",
        "Native libopus",
        "--features real-audio",
    ] {
        assert!(help.contains(marker), "help omitted {marker}:\n{help}");
    }
    assert_eq!(run(&[]).status.code(), Some(EXIT_USAGE));
}

#[test]
fn fake_peer_exercises_media_data_channel_and_clean_teardown() {
    let output = run(&["--fake", "--timeout-seconds", "10"]);
    assert!(
        output.status.success(),
        "stdout:\n{}\nstderr:\n{}",
        text(&output.stdout),
        text(&output.stderr)
    );
    let stdout = text(&output.stdout);
    for marker in [
        "ice=connected",
        "dtls=connected",
        "srtp=opus",
        "sctp=SLData",
        "sent-audio=4",
        "active-peer-tasks=0",
        "active-audio-tasks=0",
    ] {
        assert!(
            stdout.contains(marker),
            "output omitted {marker}:\n{stdout}"
        );
    }
    assert!(output.stderr.is_empty(), "{}", text(&output.stderr));
}

#[test]
fn virtual_devices_are_available_without_physical_hardware() {
    let output = run(&["--list-devices"]);
    assert!(output.status.success(), "{}", text(&output.stderr));
    let stdout = text(&output.stdout);
    assert!(stdout.contains("input\tvirtual:microphone"));
    assert!(stdout.contains("output\tvirtual:speaker"));
}

#[test]
fn live_inputs_are_rejected_before_network_without_both_opt_ins_or_secret_echo() {
    let output = run(&["First", "Last", "do-not-echo"]);
    assert_eq!(output.status.code(), Some(EXIT_USAGE));
    assert!(text(&output.stderr).contains("--allow-live-login"));
    assert!(!text(&output.stderr).contains("do-not-echo"));

    let output = run(&[
        "First",
        "Last",
        "do-not-echo",
        "--allow-live-login",
        "--confirm-live-login",
        "WRONG",
    ]);
    assert_eq!(output.status.code(), Some(EXIT_USAGE));
    assert!(!text(&output.stderr).contains("do-not-echo"));

    let output = run(&["First", "Last", "do-not-echo", "--fake"]);
    assert_eq!(output.status.code(), Some(EXIT_USAGE));
    assert!(!text(&output.stderr).contains("do-not-echo"));
}
