//! Comprehensive Analytics System
//!
//! This module provides unified analytics, monitoring, and supervision capabilities
//! that integrate route cache generation, navigation tracking, server logs, and browser logs.
//!
//! # Architecture
//!
//! - **Collector**: Unified data collection from all sources
//! - **Analyzer**: Real-time and batch analysis engine
//! - **Reporter**: Report generation and export
//! - **Search**: Cross-log search and filtering
//! - **Supervisor**: Continuous monitoring and alerting
//!
//! # Integration Points
//!
//! - Navigation tracking (JSONL logs)
//! - Route cache performance metrics
//! - Server logs (tracing output)
//! - Browser logs (console, hydration errors)
//! - Manager dashboard integration
//! - CLI tools for queries and reports

use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;

pub mod browser;
pub mod collector;
pub mod navigation;
pub mod reporter;
pub mod search;
pub mod server;
pub mod supervisor;

// Re-export main types for easy access
pub use collector::{AnalyticsCollector, LogSource};
pub use reporter::{AnalyticsReporter, ReportConfig, ReportFormat};
pub use search::{AnalyticsSearch, SearchQuery, SearchResult};
pub use supervisor::{AnalyticsSupervisor, AlertConfig, AlertType};

/// Configuration for the analytics system
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalyticsConfig {
    /// Enable/disable analytics collection
    pub enabled: bool,
    /// Log retention period in days
    pub log_retention_days: u32,
    /// Directory for analytics data storage
    pub data_directory: PathBuf,
    /// Alert configuration
    pub alerts: AlertConfig,
    /// Export formats
    pub export_formats: Vec<ReportFormat>,
    /// External integrations
    pub integrations: IntegrationConfig,
}

impl Default for AnalyticsConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            log_retention_days: 30,
            data_directory: PathBuf::from("logs/analytics"),
            alerts: AlertConfig::default(),
            export_formats: vec![ReportFormat::Json, ReportFormat::Html],
            integrations: IntegrationConfig::default(),
        }
    }
}

/// External integration configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IntegrationConfig {
    /// Elasticsearch integration
    pub elasticsearch: Option<ElasticsearchConfig>,
    /// Grafana integration
    pub grafana: Option<GrafanaConfig>,
    /// Custom webhook endpoints
    pub webhooks: Vec<WebhookConfig>,
}

impl Default for IntegrationConfig {
    fn default() -> Self {
        Self {
            elasticsearch: None,
            grafana: None,
            webhooks: Vec::new(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ElasticsearchConfig {
    pub url: String,
    pub index_prefix: String,
    pub credentials: Option<(String, String)>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GrafanaConfig {
    pub url: String,
    pub api_key: String,
    pub dashboard_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebhookConfig {
    pub name: String,
    pub url: String,
    pub events: Vec<String>,
    pub headers: HashMap<String, String>,
}

/// Unified analytics event structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalyticsEvent {
    /// Unique event ID
    pub id: String,
    /// Timestamp when event occurred
    pub timestamp: DateTime<Utc>,
    /// Event source (navigation, server, browser, cache)
    pub source: LogSource,
    /// Event type/category
    pub event_type: String,
    /// Session identifier
    pub session_id: Option<String>,
    /// Request path or identifier
    pub path: Option<String>,
    /// Event severity level
    pub level: EventLevel,
    /// Event message or description
    pub message: String,
    /// Additional structured data
    pub metadata: HashMap<String, serde_json::Value>,
    /// Processing duration (if applicable)
    pub duration_ms: Option<u64>,
    /// Associated errors
    pub errors: Vec<String>,
}

/// Event severity levels
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
pub enum EventLevel {
    Trace,
    Debug,
    Info,
    Warn,
    Error,
    Critical,
}

impl EventLevel {
    pub fn as_str(&self) -> &'static str {
        match self {
            EventLevel::Trace => "trace",
            EventLevel::Debug => "debug",
            EventLevel::Info => "info",
            EventLevel::Warn => "warn",
            EventLevel::Error => "error",
            EventLevel::Critical => "critical",
        }
    }
}

/// Analytics metrics aggregated over time periods
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalyticsMetrics {
    /// Time period for these metrics
    pub period_start: DateTime<Utc>,
    pub period_end: DateTime<Utc>,

    /// Navigation metrics
    pub navigation: NavigationMetrics,
    /// Cache metrics
    pub cache: CacheMetrics,
    /// Server metrics
    pub server: ServerMetrics,
    /// Browser metrics
    pub browser: BrowserMetrics,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NavigationMetrics {
    pub total_requests: u64,
    pub route_resolutions: u64,
    pub language_switches: u64,
    pub avg_resolution_time_ms: f64,
    pub slow_routes_count: u64,
    pub error_count: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheMetrics {
    pub total_requests: u64,
    pub hit_count: u64,
    pub miss_count: u64,
    pub hit_rate: f64,
    pub evictions: u64,
    pub expired_entries: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerMetrics {
    pub total_requests: u64,
    pub error_count: u64,
    pub panic_count: u64,
    pub avg_response_time_ms: f64,
    pub memory_usage_mb: Option<f64>,
    pub cpu_usage_percent: Option<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrowserMetrics {
    pub console_errors: u64,
    pub console_warnings: u64,
    pub hydration_mismatches: u64,
    pub javascript_errors: u64,
    pub performance_issues: u64,
}

/// Main analytics engine
pub struct Analytics {
    config: AnalyticsConfig,
    collector: AnalyticsCollector,
    reporter: AnalyticsReporter,
    search: AnalyticsSearch,
    supervisor: AnalyticsSupervisor,
}

impl Analytics {
    /// Create new analytics engine
    pub fn new(config: AnalyticsConfig) -> Result<Self> {
        let collector = AnalyticsCollector::new(&config)?;
        let reporter = AnalyticsReporter::new(&config)?;
        let search = AnalyticsSearch::new(&config)?;
        let supervisor = AnalyticsSupervisor::new(&config)?;

        Ok(Self {
            config,
            collector,
            reporter,
            search,
            supervisor,
        })
    }

    /// Start analytics collection and monitoring
    pub async fn start(&mut self) -> Result<()> {
        if !self.config.enabled {
            tracing::info!("Analytics disabled in configuration");
            return Ok(());
        }

        tracing::info!("Starting analytics system...");

        // Start data collection from all sources
        self.collector.start().await?;

        // Start continuous monitoring
        self.supervisor.start().await?;

        tracing::info!("Analytics system started successfully");
        Ok(())
    }

    /// Stop analytics collection
    pub async fn stop(&mut self) -> Result<()> {
        tracing::info!("Stopping analytics system...");

        self.collector.stop().await?;
        self.supervisor.stop().await?;

        tracing::info!("Analytics system stopped");
        Ok(())
    }

    /// Get current metrics
    pub async fn get_metrics(&self, period_hours: u32) -> Result<AnalyticsMetrics> {
        self.collector.get_aggregated_metrics(period_hours).await
    }

    /// Search analytics data
    pub async fn search(&self, query: SearchQuery) -> Result<Vec<SearchResult>> {
        self.search.search(query).await
    }

    /// Generate report
    pub async fn generate_report(&self, config: ReportConfig) -> Result<String> {
        self.reporter.generate(config).await
    }

    /// Get analytics configuration
    pub fn config(&self) -> &AnalyticsConfig {
        &self.config
    }
}

/// Initialize analytics from project configuration
pub fn init_analytics_from_config(project_root: &std::path::Path) -> Result<Analytics> {
    // Load configuration from project config.toml
    let config_path = project_root.join("config.toml");

    let config = if config_path.exists() {
        let config_content = std::fs::read_to_string(config_path)?;
        let full_config: toml::Value = toml::from_str(&config_content)?;

        // Extract analytics section if it exists
        full_config
            .get("analytics")
            .map(|v| v.clone().try_into())
            .transpose()?
            .unwrap_or_default()
    } else {
        AnalyticsConfig::default()
    };

    Analytics::new(config)
}

/// Utility function to create a UUID for event tracking
pub fn generate_event_id() -> String {
    use std::sync::atomic::{AtomicU64, Ordering};
    static COUNTER: AtomicU64 = AtomicU64::new(0);

    let timestamp = chrono::Utc::now().timestamp_millis() as u64;
    let counter = COUNTER.fetch_add(1, Ordering::SeqCst);

    format!("evt_{}_{}", timestamp, counter)
}

/// Utility function to determine session ID from various sources
pub fn resolve_session_id(
    nav_session: Option<&str>,
    server_session: Option<&str>
) -> String {
    nav_session
        .or(server_session)
        .map(|s| s.to_string())
        .unwrap_or_else(|| {
            format!("session_{}", chrono::Utc::now().timestamp_millis())
        })
}
