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 starter: TierRateLimits,
    pub growth: TierRateLimits,
    pub enterprise: 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,
            starter: TierRateLimits { standard: 60, compute_heavy: 5, webhook: 60 },
            growth: TierRateLimits { standard: 200, compute_heavy: 20, webhook: 200 },
            enterprise: TierRateLimits { standard: 1000, compute_heavy: 100, webhook: 1000 },
        }
    }
}

#[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>,
    #[serde(default)]
    pub rate_limit: RateLimitConfig,
}

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()
    }
}
