use clap::{Args, Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(name = "closure")]
#[command(about = "Manage coding agent configurations and credentials")]
pub struct Cli {
    #[command(subcommand)]
    pub command: Option<Commands>,

    #[arg(long, global = true)]
    pub tui: bool,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
    #[command(alias = "cc")]
    ClaudeCode {
        #[command(subcommand)]
        command: AgentCommands,
    },
    #[command(alias = "cx")]
    Codex {
        #[command(subcommand)]
        command: AgentCommands,
    },
    Auth {
        #[command(subcommand)]
        command: Option<AuthCommands>,
    },
    /// Initialize a new encrypted vault
    Init,
    /// Sync workdata with a git-backed sync directory
    Sync,
    /// Set the git remote for the sync directory
    #[command(name = "set-upstream")]
    SetUpstream {
        url: String,
    },
}

#[derive(Subcommand, Debug)]
pub enum AgentCommands {
    #[command(alias = "p")]
    Provider {
        #[command(subcommand)]
        command: ProviderCommands,
    },
}

#[derive(Subcommand, Debug)]
pub enum ProviderCommands {
    #[command(alias = "s")]
    Select { name: String },
    #[command(aliases = ["l", "ls"])]
    List,
    #[command(alias = "a")]
    Add {
        name: String,
        #[command(flatten)]
        args: ProviderAddEditArgs,
    },
    #[command(alias = "e")]
    Edit {
        name: String,
        #[command(flatten)]
        args: ProviderAddEditArgs,
    },
    #[command(alias = "r")]
    Remove { name: String },
}

#[derive(Args, Debug, Clone)]
pub struct ProviderAddEditArgs {
    /// Model name
    #[arg(long)]
    pub model: Option<String>,

    /// API key (Codex only)
    #[arg(long)]
    pub key: Option<String>,

    /// Base URL (Codex only)
    #[arg(long)]
    pub url: Option<String>,

    /// Model provider name, e.g. "OpenAI" (Codex only)
    #[arg(long = "provider")]
    pub model_provider: Option<String>,

    /// Review model name (Codex only)
    #[arg(long = "review-model")]
    pub review_model: Option<String>,

    /// Environment variable KEY=VALUE (Claude Code only, repeatable)
    #[arg(long = "env", value_parser = parse_env_kv)]
    pub env: Vec<(String, String)>,
}

fn parse_env_kv(arg: &str) -> Result<(String, String), String> {
    let (k, v) = arg
        .split_once('=')
        .ok_or_else(|| format!("expected KEY=VALUE, got: {}", arg))?;
    Ok((k.to_string(), v.to_string()))
}

#[derive(Subcommand, Debug)]
pub enum AuthCommands {
    Logout,
}
