//! Integration: spawn the kebab binary and parse `kebab schema [--json]`.
//!
//! Each test builds an isolated TempDir-rooted XDG layout, runs
//! `kebab ingest` over an empty workspace (which creates and migrates
//! kebab.sqlite), then exercises `kebab schema` in JSON and text modes.
//! Using an empty workspace avoids the embedding model dependency while
//! still seeding the DB so `open_existing` inside schema_with_config
//! succeeds (a NotIndexed error fires when the DB file is absent).

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 xdg_envs(tmp: &std::path::Path) -> [(&'static str, std::path::PathBuf); 4] {
    [
        ("XDG_CONFIG_HOME", tmp.join("cfg")),
        ("XDG_DATA_HOME", tmp.join("data")),
        ("XDG_CACHE_HOME", tmp.join("cache")),
        ("XDG_STATE_HOME", tmp.join("state")),
    ]
}

/// Seed kebab.sqlite by running `kebab ingest` over an empty workspace dir.
/// This is the minimum required for `kebab schema` to succeed: the store
/// uses `open_existing`, which errors when the DB file is absent.
fn seed_db(tmp: &tempfile::TempDir) {
    let ws = tmp.path().join("ws");
    std::fs::create_dir_all(&ws).unwrap();

    let mut cmd = Command::new(kebab_bin());
    cmd.args(["ingest", "--root", ws.to_str().unwrap(), "--summary-only"]);
    for (k, v) in xdg_envs(tmp.path()) {
        cmd.env(k, v);
    }
    let out = cmd.output().unwrap();
    assert!(
        out.status.success(),
        "seed ingest failed: {}",
        String::from_utf8_lossy(&out.stderr)
    );
}

#[test]
fn cli_schema_json_emits_schema_v1() {
    let tmp = tempfile::tempdir().unwrap();
    seed_db(&tmp);

    let mut cmd = Command::new(kebab_bin());
    cmd.args(["--json", "schema"]);
    for (k, v) in xdg_envs(tmp.path()) {
        cmd.env(k, v);
    }
    let out = cmd.output().unwrap();
    assert!(
        out.status.success(),
        "kebab --json schema failed: {}",
        String::from_utf8_lossy(&out.stderr)
    );

    let stdout = String::from_utf8(out.stdout).unwrap();
    let v: serde_json::Value = serde_json::from_str(&stdout).expect("stdout must be valid JSON");

    assert_eq!(
        v.get("schema_version").and_then(|s| s.as_str()),
        Some("schema.v1"),
        "schema_version must be schema.v1"
    );
    assert!(
        v.get("kebab_version")
            .and_then(|s| s.as_str())
            .is_some_and(|s| !s.is_empty()),
        "kebab_version must be a non-empty string"
    );

    let caps = v
        .get("capabilities")
        .and_then(|c| c.as_object())
        .expect("capabilities must be a JSON object");
    assert_eq!(
        caps.get("json_mode").and_then(serde_json::Value::as_bool),
        Some(true),
        "capabilities.json_mode must be true"
    );
    assert_eq!(
        caps.get("mcp_server").and_then(serde_json::Value::as_bool),
        Some(true),
        "capabilities.mcp_server must be true (fb-30)"
    );
}

#[test]
fn cli_schema_text_mode_runs() {
    let tmp = tempfile::tempdir().unwrap();
    seed_db(&tmp);

    let mut cmd = Command::new(kebab_bin());
    cmd.args(["schema"]);
    for (k, v) in xdg_envs(tmp.path()) {
        cmd.env(k, v);
    }
    let out = cmd.output().unwrap();
    assert!(
        out.status.success(),
        "kebab schema (text) failed: {}",
        String::from_utf8_lossy(&out.stderr)
    );

    let stdout = String::from_utf8(out.stdout).unwrap();
    assert!(
        stdout.contains("kebab v"),
        "text output must contain 'kebab v', got: {stdout}"
    );
    assert!(
        stdout.contains("capabilities"),
        "text output must contain 'capabilities', got: {stdout}"
    );
    assert!(
        stdout.contains("models"),
        "text output must contain 'models', got: {stdout}"
    );
    assert!(
        stdout.contains("stats"),
        "text output must contain 'stats', got: {stdout}"
    );
}
