use std::collections::HashMap;

/// 单个 LLM Provider 配置
#[derive(serde::Deserialize, Clone, Debug)]
pub struct LlmProviderConfig {
    pub name: String,
    pub base_url: String,
    pub api_key: String,
    pub model: String,
    #[serde(default)]
    pub api_format: Option<String>,
    #[serde(default)]
    pub max_tokens: Option<u32>,
    #[serde(default)]
    pub temperature: Option<f64>,
    #[serde(default)]
    pub params: Option<toml::Value>,
}

/// Agent worker 配置
#[derive(serde::Deserialize, Clone, Debug)]
pub struct AgentWorkerConfig {
    pub task_type: String,
    pub provider: String,
    #[serde(default)]
    pub max_turns: Option<u32>,
    #[serde(default)]
    pub temperature: Option<f64>,
}

/// 配置文件解析结构
#[derive(serde::Deserialize)]
struct ConfigFile {
    #[serde(default)]
    ai: Option<AIConfig>,
    #[serde(default)]
    api_key: Option<String>,
    #[serde(default)]
    deepseek_api_key: Option<String>,
    #[serde(default)]
    cors_origins: Option<Vec<String>>,
}

#[derive(serde::Deserialize)]
struct AIConfig {
    #[serde(default)]
    default_provider: Option<String>,
    #[serde(default)]
    providers: HashMap<String, LlmProviderFileConfig>,
    #[serde(default)]
    workers: Vec<AgentWorkerConfig>,
}

#[derive(serde::Deserialize)]
struct LlmProviderFileConfig {
    base_url: String,
    api_key: String,
    #[serde(default)]
    model: Option<String>,
    #[serde(default)]
    api_format: Option<String>,
    #[serde(default)]
    max_tokens: Option<u32>,
    #[serde(default)]
    temperature: Option<f64>,
    #[serde(default)]
    params: Option<toml::Value>,
}

#[derive(serde::Deserialize, Clone)]
pub struct Config {
    pub(crate) api_key: Option<String>,
    pub(crate) deepseek_api_key: Option<String>,
    pub(crate) cors_origins: Option<Vec<String>>,
    pub(crate) providers: HashMap<String, LlmProviderConfig>,
    pub(crate) agent_workers: Vec<AgentWorkerConfig>,
    pub(crate) default_provider: Option<String>,
}

pub fn load_config(deepseek_cli_key: Option<String>, api_cli_key: Option<String>) -> Config {
    // Search config files in priority order: ./theseus.toml > ~/.config/theseus/config.toml
    let candidates = [std::path::PathBuf::from("theseus.toml"), dirs_config_path()];
    let mut config = Config {
        api_key: None,
        deepseek_api_key: None,
        cors_origins: None,
        providers: HashMap::new(),
        agent_workers: Vec::new(),
        default_provider: None,
    };

    for path in &candidates {
        if path.exists() {
            let content = std::fs::read_to_string(path).unwrap_or_default();
            if let Ok(file_config) = toml::from_str::<ConfigFile>(&content) {
                // Handle legacy deepseek_api_key field
                if let Some(key) = file_config.deepseek_api_key {
                    config.deepseek_api_key = Some(key);
                }

                // Handle new [ai] section
                if let Some(ai_config) = file_config.ai {
                    config.default_provider = ai_config.default_provider;

                    // Parse providers
                    for (name, provider) in ai_config.providers {
                        let provider_config = LlmProviderConfig {
                            name: name.clone(),
                            base_url: provider.base_url,
                            api_key: provider.api_key,
                            model: provider.model.unwrap_or_else(|| "default".to_string()),
                            api_format: provider.api_format,
                            max_tokens: provider.max_tokens,
                            temperature: provider.temperature,
                            params: provider.params,
                        };
                        config.providers.insert(name, provider_config);
                    }

                    // Parse workers
                    config.agent_workers = ai_config.workers;
                }

                if let Ok(env_key) = std::env::var("THESEUS_API_KEY") {
                    if !env_key.trim().is_empty() {
                        config.api_key = Some(env_key);
                    }
                }
                if let Ok(env_key) = std::env::var("THESEUS_DEEPSEEK_API_KEY") {
                    if !env_key.trim().is_empty() {
                        config.deepseek_api_key = Some(env_key);
                    }
                }
                break;
            }
        }
    }

    if let Ok(env_key) = std::env::var("THESEUS_API_KEY") {
        if !env_key.trim().is_empty() {
            config.api_key = Some(env_key);
        }
    }
    if let Ok(env_key) = std::env::var("THESEUS_DEEPSEEK_API_KEY") {
        if !env_key.trim().is_empty() {
            config.deepseek_api_key = Some(env_key);
        }
    }
    if let Ok(env_origins) = std::env::var("THESEUS_CORS_ORIGINS") {
        let origins: Vec<String> = env_origins
            .split(',')
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .collect();
        if !origins.is_empty() {
            config.cors_origins = Some(origins);
        }
    }
    if let Some(key) = api_cli_key {
        config.api_key = Some(key);
    }
    if let Some(key) = deepseek_cli_key {
        config.deepseek_api_key = Some(key);
    }

    // Backward compatibility: if no providers configured but deepseek_api_key exists,
    // create a default provider entry
    if config.providers.is_empty() {
        if let Some(ref key) = config.deepseek_api_key {
            config.providers.insert(
                "deepseek".to_string(),
                LlmProviderConfig {
                    name: "deepseek".to_string(),
                    base_url: "https://api.deepseek.com".to_string(),
                    api_key: key.clone(),
                    model: "deepseek-v4-flash".to_string(),
                    api_format: Some("openai".to_string()),
                    max_tokens: None,
                    temperature: None,
                    params: None,
                },
            );
            config.default_provider = Some("deepseek".to_string());
        }
    }

    config
}

fn dirs_config_path() -> std::path::PathBuf {
    // XDG_CONFIG_HOME or ~/.config/theseus/config.toml
    let base = std::env::var("XDG_CONFIG_HOME")
        .map(std::path::PathBuf::from)
        .unwrap_or_else(|_| dirs_home().join(".config"));
    base.join("theseus").join("config.toml")
}

fn dirs_home() -> std::path::PathBuf {
    std::env::var("HOME")
        .map(std::path::PathBuf::from)
        .unwrap_or_else(|_| std::path::PathBuf::from("/"))
}
