use serde::Deserialize;
use std::collections::HashMap;

#[derive(Debug, Clone, Deserialize)]
pub struct AppConfig {
    pub proxy_port: u16,
    pub api_port: u16,
    pub database_url: String,
    pub redis_url: String,
    pub timescale_url: String,
    pub jwt_secret: String,
    pub auth_mode: AuthMode,
    pub governance_mode: GovernanceMode,
    pub providers: HashMap<String, ProviderConfig>,
    pub telemetry_channel_size: usize,
}

#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum AuthMode {
    Local,
    OAuth,
}

#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum GovernanceMode {
    Strict,
    Audit,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ProviderConfig {
    pub api_key: String,
    pub base_url: String,
}

impl AppConfig {
    pub fn from_env() -> anyhow::Result<Self> {
        dotenvy::dotenv().ok();

        let mut providers = HashMap::new();
        if let Ok(key) = std::env::var("OPENAI_API_KEY") {
            providers.insert("openai".to_string(), ProviderConfig {
                api_key: key,
                base_url: std::env::var("OPENAI_BASE_URL")
                    .unwrap_or_else(|_| "https://api.openai.com".to_string()),
            });
        }
        if let Ok(key) = std::env::var("ANTHROPIC_API_KEY") {
            providers.insert("anthropic".to_string(), ProviderConfig {
                api_key: key,
                base_url: std::env::var("ANTHROPIC_BASE_URL")
                    .unwrap_or_else(|_| "https://api.anthropic.com".to_string()),
            });
        }

        Ok(Self {
            proxy_port: std::env::var("PROXY_PORT")
                .unwrap_or_else(|_| "8080".to_string())
                .parse()?,
            api_port: std::env::var("API_PORT")
                .unwrap_or_else(|_| "3000".to_string())
                .parse()?,
            database_url: std::env::var("DATABASE_URL")
                .unwrap_or_else(|_| "postgres://dd0c:dd0c@localhost:5432/dd0c".to_string()),
            redis_url: std::env::var("REDIS_URL")
                .unwrap_or_else(|_| "redis://localhost:6379".to_string()),
            timescale_url: std::env::var("TIMESCALE_URL")
                .unwrap_or_else(|_| "postgres://dd0c:dd0c@localhost:5433/dd0c_telemetry".to_string()),
            jwt_secret: std::env::var("JWT_SECRET")
                .unwrap_or_else(|_| "dev-secret-change-me".to_string()),
            auth_mode: if std::env::var("AUTH_MODE").unwrap_or_default() == "oauth" {
                AuthMode::OAuth
            } else {
                AuthMode::Local
            },
            governance_mode: if std::env::var("GOVERNANCE_MODE").unwrap_or_default() == "strict" {
                GovernanceMode::Strict
            } else {
                GovernanceMode::Audit
            },
            providers,
            telemetry_channel_size: std::env::var("TELEMETRY_CHANNEL_SIZE")
                .unwrap_or_else(|_| "1000".to_string())
                .parse()
                .unwrap_or(1000),
        })
    }

    pub fn provider_url(&self, provider: &str) -> String {
        self.providers
            .get(provider)
            .map(|p| p.base_url.clone())
            .unwrap_or_else(|| "https://api.openai.com".to_string())
    }

    pub fn provider_key(&self, provider: &str) -> String {
        self.providers
            .get(provider)
            .map(|p| p.api_key.clone())
            .unwrap_or_default()
    }
}
