mod types;
mod nodes;
mod edges;
mod graph;

use anyhow::Result;
use clap::Parser;
use std::path::PathBuf;

#[derive(Parser)]
#[command(name = "kei-graph-export", about = "Export KeiSei graph as D3 space fragment")]
struct Cli {
    #[arg(long)]
    registry_db: Option<PathBuf>,

    #[arg(long)]
    ledger_db: Option<PathBuf>,

    #[arg(long)]
    manifests_dir: Option<PathBuf>,

    #[arg(long, default_value = "spaces-fragment")]
    format: String,

    #[arg(long, short = 'o')]
    output: Option<PathBuf>,
}

fn home_path(suffix: &str) -> PathBuf {
    let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
    PathBuf::from(home).join(suffix)
}

fn main() -> Result<()> {
    let cli = Cli::parse();

    let registry_db = cli.registry_db
        .or_else(|| std::env::var("KEI_REGISTRY_DB").ok().map(PathBuf::from))
        .unwrap_or_else(|| home_path(".claude/registry.sqlite"));
    let ledger_db = cli.ledger_db
        .or_else(|| std::env::var("KEI_LEDGER_DB").ok().map(PathBuf::from))
        .unwrap_or_else(|| home_path(".claude/agents/ledger.sqlite"));
    let manifests_dir = cli.manifests_dir
        .unwrap_or_else(|| home_path("Projects/KeiSeiKit-public/_manifests"));

    let cfg = graph::GraphConfig { registry_db, ledger_db, manifests_dir };
    let space = graph::build_graph(&cfg)?;

    let content = match cli.format.as_str() {
        "json" => serde_json::to_string_pretty(&space.data)?,
        // window.RUNTIME_SPACE = ... — assigning to global avoids the
        // `const RUNTIME_SPACE` re-declaration error when the auto-refresh
        // script re-evaluates this file every 5s in the browser.
        _ => format!(
            "// Auto-generated by kei-graph-export — do not edit.\n\
             window.RUNTIME_SPACE = {};\n",
            serde_json::to_string(&space)?
        ),
    };

    match cli.output {
        Some(path) => std::fs::write(path, content)?,
        None => print!("{}", content),
    }
    Ok(())
}
