pub mod cli;
pub mod convert;
pub mod diff;
pub mod sync;

pub use cli::{Cli, Client};

use anyhow::Result;
use serde_json::{Map, Value};
use std::fs;
use std::path::PathBuf;

/// Load mcpServers.json, returning a map of server name -> config.
fn load_source_config(path: &PathBuf) -> Result<Map<String, Value>> {
    if !path.exists() {
        anyhow::bail!("config file not found: {}", path.display());
    }
    let content = fs::read_to_string(path)?;
    let value: Value = serde_json::from_str(&content)?;
    let map = value
        .as_object()
        .ok_or_else(|| anyhow::anyhow!("config file must be a JSON object"))?
        .clone();
    Ok(map)
}

/// Resolve the source config path: explicit flag, or the default under the home directory.
fn resolve_config_path(explicit: Option<PathBuf>) -> Result<PathBuf> {
    if let Some(p) = explicit {
        return Ok(p);
    }
    let home =
        dirs::home_dir().ok_or_else(|| anyhow::anyhow!("cannot determine home directory"))?;
    Ok(home.join("data/config/ai_conf/mcpServers.json"))
}

/// Sync the source config to every requested client using its strategy.
pub fn run(cli: Cli) -> Result<()> {
    let config_path = resolve_config_path(cli.config)?;
    let source = load_source_config(&config_path)?;
    println!(
        "Loaded {} MCP servers from {}",
        source.len(),
        config_path.display()
    );

    let home =
        dirs::home_dir().ok_or_else(|| anyhow::anyhow!("cannot determine home directory"))?;

    for client in &cli.clients {
        sync::strategy(client).sync(&source, &home)?;
    }
    Ok(())
}
