//! `hephaes config` / `providers` / `login` — configuration management.

use super::base_overrides;
use crate::cli::{ConfigAction, ConfigArgs, GlobalArgs, LoginArgs};
use crate::config::{self, Overrides, Paths, ProviderId};
use crate::providers::{
    AnthropicProvider, ClaudeProvider, CodexProvider, Flavor, OpenAiCompat, Provider, ProviderKind,
};
use crate::{onboarding, secret};
use anyhow::Result;
use owo_colors::OwoColorize;

pub async fn run(args: ConfigArgs) -> Result<()> {
    let root = std::env::current_dir()?;
    let paths = Paths::new(&root);

    match args.action.unwrap_or(ConfigAction::Show) {
        ConfigAction::Show => {
            println!("{}", "configuration".bold());
            println!("project config: {}", paths.project_config.display());
            println!("global config:  {}", paths.global_config.display());
            println!("secret backend: {}", secret::backend_name());
            match config::resolve(&paths, &Overrides::default())? {
                Some(cfg) => {
                    println!("\nresolved:");
                    println!("  provider   = {}", cfg.provider.as_str());
                    println!(
                        "  model      = {}",
                        cfg.model.as_deref().unwrap_or("(default)")
                    );
                    println!("  wiki_dir   = {}", cfg.wiki_dir);
                    println!("  ollama_url = {}", cfg.ollama_url);
                    println!("  max_file_bytes = {}", cfg.max_file_bytes);
                }
                None => println!(
                    "\n{}",
                    "no provider configured (run `hephaes login`)".yellow()
                ),
            }
        }
        ConfigAction::Set { key, value } => {
            config::set_key(&paths, &key, &value)?;
            println!("{} {key} = {value}", "set:".green());
        }
        ConfigAction::Path => {
            println!("{}", paths.project_config.display());
        }
    }
    Ok(())
}

pub async fn providers() -> Result<()> {
    let root = std::env::current_dir()?;
    let paths = Paths::new(&root);

    println!("{:<11} {:<13} {:<11} key", "provider", "kind", "auth");
    for id in ProviderId::all() {
        let p = lightweight(id, &paths);
        let kind = match p.kind() {
            ProviderKind::NativeAgent => "native-agent",
            ProviderKind::RawModel => "raw-model",
        };
        let auth = p.auth_status().await;
        let key = secret::key_source(&paths, p.id()).unwrap_or("-");
        let auth_disp = if auth.is_ok() {
            auth.label().green().to_string()
        } else {
            auth.label().yellow().to_string()
        };
        println!(
            "{:<11} {:<13} {:<11} {}",
            p.id().as_str(),
            kind,
            auth_disp,
            key
        );
    }
    Ok(())
}

pub async fn login(global: &GlobalArgs, args: LoginArgs) -> Result<()> {
    let root = std::env::current_dir()?;
    let paths = Paths::new(&root);
    let ov = base_overrides(global);
    let cfg = onboarding::run_wizard(&paths, &ov, args.provider).await?;
    println!("{} provider {} ready.", "✓".green(), cfg.provider.as_str());
    Ok(())
}

/// Construct a provider just for `auth_status` (no model needed, never fails).
fn lightweight(id: ProviderId, paths: &Paths) -> Box<dyn Provider> {
    match id {
        ProviderId::Claude => Box::new(ClaudeProvider::new(None)),
        ProviderId::Codex => Box::new(CodexProvider::new(None)),
        ProviderId::Anthropic => Box::new(AnthropicProvider::new(secret::get_key(paths, id), None)),
        ProviderId::Openai => Box::new(OpenAiCompat::new(
            Flavor::OpenAi,
            "https://api.openai.com/v1".to_string(),
            secret::get_key(paths, id),
            None,
        )),
        ProviderId::Openrouter => Box::new(OpenAiCompat::new(
            Flavor::OpenRouter,
            "https://openrouter.ai/api/v1".to_string(),
            secret::get_key(paths, id),
            None,
        )),
        ProviderId::Ollama => Box::new(OpenAiCompat::new(
            Flavor::Ollama,
            format!("{}/v1", config::DEFAULT_OLLAMA_URL),
            None,
            None,
        )),
    }
}
