use serde::Deserialize;
use config::{Config, ConfigError, File, Environment};
use std::env;

#[derive(Debug, Deserialize, Clone)]
pub struct DatabaseConfig {
    pub url: String,
    pub pool_size: u32,
}

#[derive(Debug, Deserialize, Clone)]
pub struct RedisConfig {
    pub url: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct AuthConfig {
    pub jwt_secret: String, // Kept for legacy if needed, but we'll use keys
    pub jwt_public_key: String,
    pub jwt_private_key: String,
    pub refresh_token_ttl_days: u32,
}

#[derive(Debug, Deserialize, Clone)]
pub struct StripeConfig {
    pub secret_key: String,
    pub webhook_secret: String,
    pub starter_price_id: String,
    pub starter_metered_price_id: String,
    pub growth_price_id: String,
    pub growth_metered_price_id: String,
    pub success_url: String,
    pub cancel_url: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct TierRateLimits {
    pub standard: i64,
    pub compute_heavy: i64,
    pub webhook: i64,
}

#[derive(Debug, Deserialize, Clone)]
pub struct RateLimitConfig {
    pub enabled: bool,
    pub fail_open: bool,
    pub unauthenticated: i64,
    pub low: TierRateLimits,
    pub medium: TierRateLimits,
    pub high: TierRateLimits,
}

impl Default for TierRateLimits {
    fn default() -> Self {
        Self {
            standard: 60,
            compute_heavy: 5,
            webhook: 60,
        }
    }
}

impl Default for RateLimitConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            fail_open: true,
            unauthenticated: 5,
            low: TierRateLimits { standard: 60, compute_heavy: 5, webhook: 60 },
            medium: TierRateLimits { standard: 200, compute_heavy: 20, webhook: 200 },
            high: TierRateLimits { standard: 1000, compute_heavy: 100, webhook: 1000 },
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct EmailConfig {
    #[serde(default = "default_smtp_host")]
    pub smtp_host: String,
    #[serde(default = "default_smtp_port")]
    pub smtp_port: u16,
    #[serde(default)]
    pub smtp_username: String,
    #[serde(default)]
    pub smtp_password: String,
    #[serde(default = "default_from_address")]
    pub from_address: String,
    #[serde(default)]
    pub enabled: bool,
}

fn default_smtp_host() -> String {
    "localhost".to_string()
}

fn default_smtp_port() -> u16 {
    587
}

fn default_from_address() -> String {
    "noreply@kanoniv.com".to_string()
}

impl Default for EmailConfig {
    fn default() -> Self {
        Self {
            smtp_host: default_smtp_host(),
            smtp_port: default_smtp_port(),
            smtp_username: String::new(),
            smtp_password: String::new(),
            from_address: default_from_address(),
            enabled: false,
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct SalesforceConfig {
    pub client_id: String,
    pub client_secret: String,
    pub redirect_uri: String,
    #[serde(default = "default_sf_api_version")]
    pub api_version: String,
}

fn default_sf_api_version() -> String {
    "v59.0".to_string()
}

#[derive(Debug, Deserialize, Clone)]
pub struct PipedriveConfig {
    pub client_id: String,
    pub client_secret: String,
    pub redirect_uri: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct LlmConfig {
    #[serde(default)]
    pub enabled: bool,
    #[serde(default)]
    pub api_key: String,
    #[serde(default = "default_llm_base_url")]
    pub base_url: String,
    #[serde(default = "default_llm_model")]
    pub model: String,
    #[serde(default = "default_llm_max_tokens")]
    pub max_tokens: u32,
    #[serde(default = "default_llm_temperature")]
    pub temperature: f32,
}

fn default_llm_base_url() -> String {
    "https://api.anthropic.com".to_string()
}

fn default_llm_model() -> String {
    "claude-sonnet-4-20250514".to_string()
}

fn default_llm_max_tokens() -> u32 {
    4096
}

fn default_llm_temperature() -> f32 {
    0.7
}

impl Default for LlmConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            api_key: String::new(),
            base_url: default_llm_base_url(),
            model: default_llm_model(),
            max_tokens: default_llm_max_tokens(),
            temperature: default_llm_temperature(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct AppConfig {
    pub port: u16,
    pub database: DatabaseConfig,
    pub redis: RedisConfig,
    pub auth: AuthConfig,
    pub env: String,
    pub cors_origins: Option<String>,
    pub stripe: Option<StripeConfig>,
    pub salesforce: Option<SalesforceConfig>,
    pub pipedrive: Option<PipedriveConfig>,
    #[serde(default)]
    pub rate_limit: RateLimitConfig,
    #[serde(default)]
    pub email: EmailConfig,
    #[serde(default)]
    pub llm: LlmConfig,
}

impl AppConfig {
    pub fn load() -> Result<Self, ConfigError> {
        let env_name = env::var("RUN_MODE").unwrap_or_else(|_| "development".into());

        let s = Config::builder()
            .add_source(File::with_name("config/default").required(false))
            .add_source(File::with_name(&format!("config/{}", env_name)).required(false))
            .add_source(Environment::with_prefix("CANNON").separator("__"))
            .build()?;

        s.try_deserialize()
    }
}
