mod common;

fn help_stdout(args: &[&str]) -> String {
    let output = common::command::rebecca().args(args).output().unwrap();

    assert!(
        output.status.success(),
        "stderr: {}",
        common::support::stderr(&output)
    );

    String::from_utf8_lossy(&output.stdout).into_owned()
}

#[test]
fn root_help_shows_completion_and_rejects_hidden_default_scan() {
    let stdout = help_stdout(&["--help"]);
    assert!(stdout.contains("--format"));
    assert!(stdout.contains("json"));
    assert!(stdout.contains("ndjson"));
    assert!(stdout.contains("completion"));
    assert!(stdout.contains("catalog"));
    assert!(stdout.contains("inspect"));
    assert!(stdout.contains("scan"));
    assert!(stdout.contains("clean"));
    assert!(stdout.contains("tui"));
    assert!(stdout.contains("purge"));
}

#[test]
fn inspect_help_shows_canonical_read_only_commands() {
    let stdout = help_stdout(&["inspect", "--help"]);
    assert!(stdout.contains("space"));
    assert!(stdout.contains("artifacts"));
    assert!(stdout.contains("lint"));
}

#[test]
fn clean_help_preserves_preview_execution_and_warning_controls() {
    let stdout = help_stdout(&["clean", "--help"]);

    assert!(stdout.contains("Build or execute a cleanup plan"));
    assert!(stdout.contains("--dry-run"));
    assert!(stdout.contains("Preview the cleanup plan without deleting anything"));
    assert!(stdout.contains("--yes"));
    assert!(stdout.contains("Move allowed targets to recoverable trash"));
    assert!(stdout.contains("--allow-moderate"));
    assert!(stdout.contains("--allow-risky"));
    assert!(stdout.contains("--allow-warning <WARNING>"));
    assert!(stdout.contains("--scan-cache"));
    assert!(stdout.contains("--no-scan-cache"));
}

#[test]
fn tui_help_shows_interactive_workbench_controls() {
    let stdout = help_stdout(&["tui", "--help"]);

    assert!(stdout.contains("interactive terminal workbench"));
    assert!(stdout.contains("--root <PATH>"));
    assert!(stdout.contains("--scan-backend <SCAN_BACKEND>"));
    assert!(stdout.contains("--entry-limit <N>"));
    assert!(stdout.contains("--screen-reader"));
    assert!(stdout.contains("--no-color"));
    assert!(!stdout.contains("--once"));
    assert!(!stdout.contains("--replay-keys"));
    assert!(!stdout.contains("--terminal-width"));
}

#[test]
fn tui_alias_renders_once_frame_for_ci() {
    let output = common::command::rebecca()
        .args(["i", "--once"])
        .output()
        .unwrap();

    assert!(
        output.status.success(),
        "stderr: {}",
        common::support::stderr(&output)
    );

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("Rebecca TUI | root-picker"));
    assert!(stdout.contains("Roots"));
}

#[test]
fn tui_without_tty_is_rejected() {
    let output = common::command::rebecca().args(["tui"]).output().unwrap();

    assert!(!output.status.success());
    let stderr = common::support::stderr(&output);
    assert!(stderr.contains("requires an interactive terminal"));
}

#[test]
fn inspect_map_help_preserves_human_output_controls() {
    let stdout = help_stdout(&["inspect", "map", "--help"]);

    assert!(stdout.contains("Inspect ranked disk usage below one or more roots"));
    assert!(stdout.contains("--no-progress"));
    assert!(stdout.contains("--progress-detail <PROGRESS_DETAIL>"));
    assert!(stdout.contains("--full-path"));
    assert!(stdout.contains("Print full paths in human ranked output"));
    assert!(stdout.contains("--no-bars"));
    assert!(stdout.contains("Hide visual usage bars"));
    assert!(stdout.contains("--bar-width <COLUMNS>"));
    assert!(stdout.contains("--screen-reader"));
    assert!(stdout.contains("--group-by <GROUP_KINDS>"));
    assert!(stdout.contains("type, extension, depth, age"));
    assert!(stdout.contains("--table <FORMAT>"));
    assert!(stdout.contains("--cleanup-advice"));
}

#[test]
fn inspect_space_help_shows_progress_controls() {
    let stdout = help_stdout(&["inspect", "space", "--help"]);

    assert!(stdout.contains("Inspect top-level disk usage below one or more roots"));
    assert!(stdout.contains("--no-progress"));
    assert!(stdout.contains("--progress-detail <PROGRESS_DETAIL>"));
}

#[test]
fn cache_doctor_help_preserves_health_contract() {
    let stdout = help_stdout(&["cache", "doctor", "--help"]);

    assert!(stdout.contains("Diagnose Rebecca cache health"));
    assert!(stdout.contains("prune recommendations"));
    assert!(stdout.contains("--format <FORMAT>"));
    assert!(stdout.contains("json"));
    assert!(stdout.contains("ndjson"));
}

#[test]
fn doctor_active_processes_help_preserves_warning_gate_contract() {
    let stdout = help_stdout(&["doctor", "active-processes", "--help"]);

    assert!(stdout.contains("Report warning-bearing cleanup rules"));
    assert!(stdout.contains("applications appear to be running"));
    assert!(stdout.contains("--format <FORMAT>"));
    assert!(stdout.contains("json"));
    assert!(stdout.contains("ndjson"));
}

#[test]
fn root_without_subcommand_prints_help_instead_of_scanning() {
    let output = common::command::rebecca().output().unwrap();

    assert!(
        output.status.success(),
        "stderr: {}",
        common::support::stderr(&output)
    );

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("Cross-platform cleanup CLI"));
    assert!(stdout.contains("completion"));
    assert!(!stdout.contains("Rebecca rules:"));
}
