//! Integration tests for `--readonly` and `--quiet` global flags (fb-28).

use std::io::Write;
use std::process::Command;

fn kebab_bin() -> std::path::PathBuf {
    let manifest = env!("CARGO_MANIFEST_DIR");
    std::path::PathBuf::from(manifest)
        .parent()
        .unwrap()
        .parent()
        .unwrap()
        .join("target/debug/kebab")
}

fn fixture_workspace() -> (tempfile::TempDir, std::path::PathBuf) {
    let tmp = tempfile::tempdir().unwrap();
    let ws = tmp.path().join("workspace");
    std::fs::create_dir_all(&ws).unwrap();
    let mut a = std::fs::File::create(ws.join("a.md")).unwrap();
    writeln!(a, "# Alpha\n\nfirst doc").unwrap();
    (tmp, ws)
}

fn xdg_envs(tmp_path: &std::path::Path) -> [(&'static str, std::path::PathBuf); 4] {
    [
        ("XDG_CONFIG_HOME", tmp_path.join("cfg")),
        ("XDG_DATA_HOME", tmp_path.join("data")),
        ("XDG_CACHE_HOME", tmp_path.join("cache")),
        ("XDG_STATE_HOME", tmp_path.join("state")),
    ]
}

#[test]
fn readonly_flag_blocks_ingest() {
    let (tmp, ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args(["--readonly", "ingest", "--root", ws.to_str().unwrap()])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(
        stderr.contains("readonly mode"),
        "expected 'readonly mode' in stderr, got: {stderr}"
    );
}

#[test]
fn readonly_flag_blocks_ingest_file() {
    let (tmp, ws) = fixture_workspace();
    let file = ws.join("a.md");
    let out = Command::new(kebab_bin())
        .args(["--readonly", "ingest-file", file.to_str().unwrap()])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}

#[test]
fn readonly_flag_blocks_ingest_stdin() {
    let (tmp, _ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args(["--readonly", "ingest-stdin", "--title", "test"])
        .env("KEBAB_READONLY", "1")
        .envs(xdg_envs(tmp.path()))
        .stdin(std::process::Stdio::null())
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}

#[test]
fn readonly_flag_blocks_reset() {
    let (tmp, _ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args(["--readonly", "reset", "--data-only", "--yes"])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}

#[test]
fn kebab_readonly_env_blocks_ingest() {
    let (tmp, ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args(["ingest", "--root", ws.to_str().unwrap()])
        .env("KEBAB_READONLY", "1")
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(stderr.contains("readonly mode"), "stderr: {stderr}");
}

#[test]
fn readonly_json_mode_emits_error_v1() {
    let (tmp, ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args([
            "--readonly",
            "--json",
            "ingest",
            "--root",
            ws.to_str().unwrap(),
        ])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert_eq!(out.status.code(), Some(1), "expected exit 1");
    let stderr = String::from_utf8_lossy(&out.stderr);
    let v: serde_json::Value = serde_json::from_str(stderr.trim())
        .unwrap_or_else(|e| panic!("expected error.v1 JSON on stderr, got {stderr:?}: {e}"));
    assert_eq!(
        v.get("schema_version").and_then(|s| s.as_str()),
        Some("error.v1"),
        "expected schema_version=error.v1"
    );
    assert_eq!(
        v.get("code").and_then(|s| s.as_str()),
        Some("readonly_mode"),
        "expected code=readonly_mode"
    );
}

#[test]
fn quiet_flag_suppresses_progress_stderr() {
    let (tmp, ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args(["--quiet", "ingest", "--root", ws.to_str().unwrap()])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert!(
        out.status.success(),
        "exit: {:?}, stderr: {}",
        out.status.code(),
        String::from_utf8_lossy(&out.stderr)
    );
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(
        stderr.is_empty(),
        "expected empty stderr with --quiet, got: {stderr}"
    );
    let stdout = String::from_utf8_lossy(&out.stdout);
    assert!(
        stdout.contains("scanned"),
        "expected report summary on stdout, got: {stdout}"
    );
}

#[test]
fn quiet_with_json_stdout_has_report_stderr_is_empty() {
    let (tmp, ws) = fixture_workspace();
    let out = Command::new(kebab_bin())
        .args([
            "--quiet",
            "--json",
            "ingest",
            "--root",
            ws.to_str().unwrap(),
        ])
        .envs(xdg_envs(tmp.path()))
        .output()
        .unwrap();

    assert!(
        out.status.success(),
        "stderr: {}",
        String::from_utf8_lossy(&out.stderr)
    );
    let stderr = String::from_utf8_lossy(&out.stderr);
    assert!(stderr.is_empty(), "expected empty stderr, got: {stderr}");
    let stdout = String::from_utf8_lossy(&out.stdout);
    let last_line = stdout.lines().last().unwrap_or("");
    let v: serde_json::Value = serde_json::from_str(last_line)
        .unwrap_or_else(|e| panic!("expected JSON on stdout last line, got {last_line:?}: {e}"));
    assert_eq!(
        v.get("schema_version").and_then(|s| s.as_str()),
        Some("ingest_report.v1")
    );
}
