// src/monitoring/metrics.rs
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Instant;

/// Complete dashboard state sent to web clients
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DashboardState {
    pub config: ConfigSnapshot,
    pub instances: Vec<InstanceMetrics>,
    pub proxies: Vec<ProxyMetrics>,
    pub yahoo_clients: Vec<YahooClientMetrics>,
    pub global: GlobalMetrics,
    pub logs: Vec<LogEntry>,
}

/// Snapshot of configuration settings
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigSnapshot {
    pub max_parallel_instances: usize,
    pub max_tasks_per_instance: usize,
    pub enable_vpn_rotation: bool,
    pub max_requests_per_session: usize,
    pub min_request_interval_ms: u64,
    pub max_retry_attempts: u32,
}

/// Metrics for a single ChromeDriver instance
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstanceMetrics {
    pub id: usize,
    pub status: InstanceStatus,
    pub current_task: Option<String>,
    pub tasks_current_session: usize,
    pub tasks_max: usize,
    pub session_requests: usize,
    pub total_requests: usize,
    pub success_count: usize,
    pub failure_count: usize,
    pub connected_proxy: Option<ProxyInfo>,
    pub last_activity: String, // Timestamp
    pub yahoo_requests: usize,
    pub yahoo_success: usize,
    pub yahoo_failures: usize,
    pub yahoo_success_rate: f64,
    pub yahoo_current_requests: u32,
    pub yahoo_max_requests: u32,
    pub yahoo_last_endpoint: Option<String>,
    pub yahoo_last_symbol: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum InstanceStatus {
    Idle,
    Active,
    Renewing,
    Error,
}

/// Information about a proxy connection
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProxyInfo {
    pub container_name: String,
    pub ip_address: String,
    pub port: u16,
    pub status: ProxyStatus,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum ProxyStatus {
    Connected,
    Disconnected,
}

/// Metrics for a proxy
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProxyMetrics {
    pub container_name: String,
    pub ip_address: String,
    pub port: u16,
    pub status: ProxyStatus,
    pub instances_using: Vec<usize>,
}

/// Metrics for a Yahoo client
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YahooClientMetrics {
    pub instance_id: usize,
    pub requests_total: usize,
    pub requests_successful: usize,
    pub requests_failed: usize,
    pub current_requests: u32,
    pub max_requests: u32,
    pub has_proxy: bool,
    pub last_activity: String,
    pub proxy_info: Option<ProxyInfo>,
}

/// Global pool metrics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalMetrics {
    pub total_requests: usize,
    pub successful_requests: usize,
    pub failed_requests: usize,
    pub success_rate: f64,
    pub session_renewals: usize,
    pub rotation_events: usize,
    pub navigation_timeouts: usize,
    pub bot_detection_hits: usize,
    pub proxy_failures: usize,
    pub uptime_seconds: u64,
    pub total_yahoo_requests: usize,
    pub successful_yahoo_requests: usize,
    pub failed_yahoo_requests: usize,
    pub yahoo_success_rate: f64,
    pub yahoo_batch_requests: usize,
    pub yahoo_session_renewals: usize,
    pub yahoo_client_count: usize,
}

/// Log entry for display in dashboard
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntry {
    pub timestamp: String,
    pub level: LogLevel,
    pub message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
    Info,
    Warn,
    Error,
}

/// Internal state tracked by monitoring service
#[derive(Debug, Clone)]
pub struct MonitoringState {
    pub instances: HashMap<usize, InstanceState>,
    pub proxies: HashMap<String, ProxyState>,
    pub yahoo_clients: HashMap<usize, YahooClientState>,
    pub global: GlobalState,
    pub start_time: Instant,
}

#[derive(Debug, Clone)]
pub struct InstanceState {
    pub id: usize,
    pub status: InstanceStatus,
    pub current_task: Option<String>,
    pub tasks_current_session: usize,
    pub tasks_max: usize,
    pub session_requests: usize,
    pub total_requests: usize,
    pub success_count: usize,
    pub failure_count: usize,
    pub connected_proxy: Option<ProxyInfo>,
    pub last_activity: Instant,
    pub yahoo_requests: usize,
    pub yahoo_success: usize,
    pub yahoo_failures: usize,
    pub yahoo_current_requests: u32,
    pub yahoo_max_requests: u32,
    pub yahoo_last_endpoint: Option<String>,
    pub yahoo_last_symbol: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ProxyState {
    pub container_name: String,
    pub ip_address: String,
    pub port: u16,
    pub status: ProxyStatus,
    pub instances_using: Vec<usize>,
}

#[derive(Debug, Clone)]
pub struct YahooClientState {
    pub instance_id: usize,
    pub requests_total: usize,
    pub requests_successful: usize,
    pub requests_failed: usize,
    pub current_requests: u32,
    pub max_requests: u32,
    pub has_proxy: bool,
    pub last_activity: Instant,
    pub proxy_info: Option<ProxyInfo>,
}

#[derive(Debug, Clone)]
pub struct GlobalState {
    pub total_requests: usize,
    pub successful_requests: usize,
    pub failed_requests: usize,
    pub session_renewals: usize,
    pub rotation_events: usize,
    pub navigation_timeouts: usize,
    pub bot_detection_hits: usize,
    pub proxy_failures: usize,
    pub total_yahoo_requests: usize,
    pub successful_yahoo_requests: usize,
    pub failed_yahoo_requests: usize,
    pub yahoo_batch_requests: usize,
    pub yahoo_session_renewals: usize,
    pub yahoo_client_count: usize,
}

impl MonitoringState {
    pub fn new() -> Self {
        Self {
            instances: HashMap::new(),
            proxies: HashMap::new(),
            yahoo_clients: HashMap::new(),
            global: GlobalState {
                total_requests: 0,
                successful_requests: 0,
                failed_requests: 0,
                session_renewals: 0,
                rotation_events: 0,
                navigation_timeouts: 0,
                bot_detection_hits: 0,
                proxy_failures: 0,
                total_yahoo_requests: 0,
                successful_yahoo_requests: 0,
                failed_yahoo_requests: 0,
                yahoo_batch_requests: 0,
                yahoo_session_renewals: 0,
                yahoo_client_count: 0,
            },
            start_time: Instant::now(),
        }
    }

    /// Convert internal state to dashboard state for web clients
    pub fn to_dashboard_state(&self, config: ConfigSnapshot, logs: Vec<LogEntry>) -> DashboardState {
        let instances: Vec<InstanceMetrics> = self
            .instances
            .values()
            .map(|inst| {
                let yahoo_success_rate = if inst.yahoo_success + inst.yahoo_failures > 0 {
                    (inst.yahoo_success as f64 / (inst.yahoo_success + inst.yahoo_failures) as f64) * 100.0
                } else {
                    0.0
                };
                
                InstanceMetrics {
                    id: inst.id,
                    status: inst.status.clone(),
                    current_task: inst.current_task.clone(),
                    tasks_current_session: inst.tasks_current_session,
                    tasks_max: inst.tasks_max,
                    session_requests: inst.session_requests,
                    total_requests: inst.total_requests,
                    success_count: inst.success_count,
                    failure_count: inst.failure_count,
                    connected_proxy: inst.connected_proxy.clone(),
                    last_activity: format_timestamp(inst.last_activity),
                    yahoo_requests: inst.yahoo_requests,
                    yahoo_success: inst.yahoo_success,
                    yahoo_failures: inst.yahoo_failures,
                    yahoo_success_rate,
                    yahoo_current_requests: inst.yahoo_current_requests,
                    yahoo_max_requests: inst.yahoo_max_requests,
                    yahoo_last_endpoint: inst.yahoo_last_endpoint.clone(),
                    yahoo_last_symbol: inst.yahoo_last_symbol.clone(),
                }
            })
            .collect();

        let proxies: Vec<ProxyMetrics> = self
            .proxies
            .values()
            .map(|proxy| ProxyMetrics {
                container_name: proxy.container_name.clone(),
                ip_address: proxy.ip_address.clone(),
                port: proxy.port,
                status: proxy.status.clone(),
                instances_using: proxy.instances_using.clone(),
            })
            .collect();

        let yahoo_clients: Vec<YahooClientMetrics> = self
            .yahoo_clients
            .values()
            .map(|client| YahooClientMetrics {
                instance_id: client.instance_id,
                requests_total: client.requests_total,
                requests_successful: client.requests_successful,
                requests_failed: client.requests_failed,
                current_requests: client.current_requests,
                max_requests: client.max_requests,
                has_proxy: client.has_proxy,
                last_activity: format_timestamp(client.last_activity),
                proxy_info: client.proxy_info.clone(),
            })
            .collect();

        let success_rate = if self.global.total_requests > 0 {
            (self.global.successful_requests as f64 / self.global.total_requests as f64) * 100.0
        } else {
            0.0
        };

        let yahoo_success_rate = if self.global.total_yahoo_requests > 0 {
            (self.global.successful_yahoo_requests as f64 / self.global.total_yahoo_requests as f64) * 100.0
        } else {
            0.0
        };

        let global = GlobalMetrics {
            total_requests: self.global.total_requests,
            successful_requests: self.global.successful_requests,
            failed_requests: self.global.failed_requests,
            success_rate,
            session_renewals: self.global.session_renewals,
            rotation_events: self.global.rotation_events,
            navigation_timeouts: self.global.navigation_timeouts,
            bot_detection_hits: self.global.bot_detection_hits,
            proxy_failures: self.global.proxy_failures,
            uptime_seconds: self.start_time.elapsed().as_secs(),
            total_yahoo_requests: self.global.total_yahoo_requests,
            successful_yahoo_requests: self.global.successful_yahoo_requests,
            failed_yahoo_requests: self.global.failed_yahoo_requests,
            yahoo_success_rate,
            yahoo_batch_requests: self.global.yahoo_batch_requests,
            yahoo_session_renewals: self.global.yahoo_session_renewals,
            yahoo_client_count: self.global.yahoo_client_count,
        };

        DashboardState {
            config,
            instances,
            proxies,
            yahoo_clients,
            global,
            logs,
        }
    }
}

fn format_timestamp(instant: Instant) -> String {
    use chrono::Local;
    Local::now().format("%H:%M:%S").to_string()
}

/// Session completion summary for logging
#[derive(Debug, Clone, Serialize)]
pub struct SessionSummary {
    pub instance_id: usize,
    pub session_start: String,
    pub session_end: String,
    pub duration_seconds: u64,
    pub total_requests: usize,
    pub successful_requests: usize,
    pub failed_requests: usize,
    pub proxy_info: Option<ProxyInfo>,
    pub renewal_reason: String, // "task_limit", "request_limit", "error"
}