use anyhow::{Context, Result};
use chrono::{self};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    // Economic calendar start (usually the earliest available on finanzen.net)
    pub economic_start_date: String,     // e.g. "2007-02-13"
    // Corporate earnings & price history start
    pub corporate_start_date: String,    // e.g. "2000-01-01" or "2010-01-01"
    // How far into the future we scrape economic events
    pub economic_lookahead_months: u32,  // default: 3
    /// Maximum number of parallel scraping tasks (default: 10).
    /// This limits concurrency to protect system load and prevent website spamming.
    #[serde(default = "default_max_parallel_instances")]
    pub max_parallel_instances: usize,

    pub max_tasks_per_instance: usize,

    /// VPN rotation configuration
    /// If set to "true", enables automatic VPN rotation between sessions
    #[serde(default)]
    pub enable_vpn_rotation: bool,

    /// Comma-separated list of VPN servers/country codes to rotate through.
    /// Example: "US-Free#1,UK-Free#1,JP-Free#1" or "US,JP,DE"
    /// If empty, VPN rotation is disabled.
    #[serde(default)]
    pub vpn_servers: String,

    /// Number of tasks per session before rotating VPN
    /// If set to 0, rotates VPN between economic and corporate phases
    #[serde(default = "default_tasks_per_session")]
    pub tasks_per_vpn_session: usize,
}

fn default_max_parallel_instances() -> usize {
    10
}

fn default_tasks_per_session() -> usize {
    0 // 0 = rotate between economic/corporate
}

fn default_protonvpn_extension_id() -> String {
    "ghmbeldphafepmbegfdlkpapadhbakde".to_string()
}

impl Default for Config {
    fn default() -> Self {
        Self {
            economic_start_date: "2007-02-13".to_string(),
            corporate_start_date: "2010-01-01".to_string(),
            economic_lookahead_months: 3,
            max_parallel_instances: default_max_parallel_instances(),
            max_tasks_per_instance: 0,
            enable_vpn_rotation: false,
            vpn_servers: String::new(),
            tasks_per_vpn_session: default_tasks_per_session(),
        }
    }
}

impl Config {
    /// Loads the configuration from environment variables using dotenvy.
    ///
    /// This function loads a `.env` file if present (via `dotenvy::dotenv()`),
    /// then retrieves each configuration value from environment variables.
    /// If a variable is missing, it falls back to the default value.
    /// Variable names are uppercase with underscores (e.g., ECONOMIC_START_DATE).
    ///
    /// # Returns
    /// The loaded Config on success.
    ///
    /// # Errors
    /// Returns an error if parsing fails (e.g., invalid integer for lookahead months).
    pub fn load() -> Result<Self> {
        // Load .env file if it exists; ignore if not found (dotenvy::dotenv returns Ok if no file)
        let _ = dotenvy::dotenv().context("Failed to load .env file (optional)")?;

        let economic_start_date = dotenvy::var("ECONOMIC_START_DATE")
            .unwrap_or_else(|_| "2007-02-13".to_string());

        let corporate_start_date = dotenvy::var("CORPORATE_START_DATE")
            .unwrap_or_else(|_| "2010-01-01".to_string());

        let economic_lookahead_months: u32 = dotenvy::var("ECONOMIC_LOOKAHEAD_MONTHS")
            .unwrap_or_else(|_| "3".to_string())
            .parse()
            .context("Failed to parse ECONOMIC_LOOKAHEAD_MONTHS as u32")?;

        let max_parallel_instances: usize = dotenvy::var("MAX_PARALLEL_INSTANCES")
            .unwrap_or_else(|_| "10".to_string())
            .parse()
            .context("Failed to parse MAX_PARALLEL_INSTANCES as usize")?;

        let max_tasks_per_instance: usize = dotenvy::var("MAX_TASKS_PER_INSTANCE")
            .unwrap_or_else(|_| "0".to_string())
            .parse()
            .context("Failed to parse MAX_TASKS_PER_INSTANCE as usize")?;

        let enable_vpn_rotation = dotenvy::var("ENABLE_VPN_ROTATION")
            .unwrap_or_else(|_| "false".to_string())
            .parse::<bool>()
            .context("Failed to parse ENABLE_VPN_ROTATION as bool")?;

        let vpn_servers = dotenvy::var("VPN_SERVERS")
            .unwrap_or_else(|_| String::new());

        let tasks_per_vpn_session: usize = dotenvy::var("TASKS_PER_VPN_SESSION")
            .unwrap_or_else(|_| "0".to_string())
            .parse()
            .context("Failed to parse TASKS_PER_VPN_SESSION as usize")?;

        Ok(Self {
            economic_start_date,
            corporate_start_date,
            economic_lookahead_months,
            max_parallel_instances,
            max_tasks_per_instance,
            enable_vpn_rotation,
            vpn_servers,
            tasks_per_vpn_session,
        })
    }

    /// Get the list of VPN servers configured for rotation
    pub fn get_vpn_servers(&self) -> Vec<String> {
        if self.vpn_servers.is_empty() {
            Vec::new()
        } else {
            self.vpn_servers
                .split(',')
                .map(|s| s.trim().to_string())
                .filter(|s| !s.is_empty())
                .collect()
        }
    }

    pub fn target_end_date(&self) -> String {
        let now = chrono::Local::now().naive_local().date();
        let future = now + chrono::Duration::days(30 * self.economic_lookahead_months as i64);
        future.format("%Y-%m-%d").to_string()
    }
}