//! APT-OSTree Monitoring Service
//! 
//! This service runs in the background to collect metrics, perform health checks,
//! and provide monitoring capabilities for the APT-OSTree system.

use std::sync::Arc;
use std::time::Duration;
use tokio::time::interval;
use tracing::{info, warn, error, debug};
use serde_json;

use apt_ostree::monitoring::{MonitoringManager, MonitoringConfig};
use apt_ostree::error::AptOstreeResult;

/// Monitoring service configuration
#[derive(Debug, Clone)]
struct MonitoringServiceConfig {
    /// Metrics collection interval in seconds
    pub metrics_interval: u64,
    /// Health check interval in seconds
    pub health_check_interval: u64,
    /// Export metrics to file
    pub export_metrics: bool,
    /// Metrics export file path
    pub metrics_file: String,
    /// Enable system resource monitoring
    pub enable_system_monitoring: bool,
    /// Enable performance monitoring
    pub enable_performance_monitoring: bool,
    /// Enable transaction monitoring
    pub enable_transaction_monitoring: bool,
}

impl Default for MonitoringServiceConfig {
    fn default() -> Self {
        Self {
            metrics_interval: 60,
            health_check_interval: 300,
            export_metrics: true,
            metrics_file: "/var/log/apt-ostree/metrics.json".to_string(),
            enable_system_monitoring: true,
            enable_performance_monitoring: true,
            enable_transaction_monitoring: true,
        }
    }
}

/// Monitoring service
struct MonitoringService {
    config: MonitoringServiceConfig,
    monitoring_manager: Arc<MonitoringManager>,
    running: bool,
}

impl MonitoringService {
    /// Create a new monitoring service
    fn new(config: MonitoringServiceConfig) -> AptOstreeResult<Self> {
        info!("Creating monitoring service with config: {:?}", config);
        
        let monitoring_config = MonitoringConfig {
            log_level: "info".to_string(),
            log_file: None,
            structured_logging: true,
            enable_metrics: true,
            metrics_interval: config.metrics_interval,
            enable_health_checks: true,
            health_check_interval: config.health_check_interval,
            enable_performance_monitoring: config.enable_performance_monitoring,
            enable_transaction_monitoring: config.enable_transaction_monitoring,
            enable_system_monitoring: config.enable_system_monitoring,
        };
        
        let monitoring_manager = Arc::new(MonitoringManager::new(monitoring_config)?);
        monitoring_manager.init_logging()?;
        
        Ok(Self {
            config,
            monitoring_manager,
            running: false,
        })
    }
    
    /// Start the monitoring service
    async fn start(&mut self) -> AptOstreeResult<()> {
        info!("Starting monitoring service");
        
        self.running = true;
        
        // Start metrics collection task
        let metrics_manager = self.monitoring_manager.clone();
        let metrics_interval = self.config.metrics_interval;
        let export_metrics = self.config.export_metrics;
        let metrics_file = self.config.metrics_file.clone();
        
        tokio::spawn(async move {
            let mut interval = interval(Duration::from_secs(metrics_interval));
            
            while let Some(_) = interval.tick().await {
                debug!("Collecting system metrics");
                
                if let Err(e) = metrics_manager.record_system_metrics().await {
                    error!("Failed to record system metrics: {}", e);
                }
                
                if export_metrics {
                    if let Err(e) = Self::export_metrics_to_file(&metrics_manager, &metrics_file).await {
                        error!("Failed to export metrics to file: {}", e);
                    }
                }
            }
        });
        
        // Start health check task
        let health_manager = self.monitoring_manager.clone();
        let health_interval = self.config.health_check_interval;
        
        tokio::spawn(async move {
            let mut interval = interval(Duration::from_secs(health_interval));
            
            while let Some(_) = interval.tick().await {
                debug!("Running health checks");
                
                match health_manager.run_health_checks().await {
                    Ok(results) => {
                        for result in results {
                            match result.status {
                                apt_ostree::monitoring::HealthStatus::Healthy => {
                                    debug!("Health check passed: {}", result.check_name);
                                }
                                apt_ostree::monitoring::HealthStatus::Warning => {
                                    warn!("Health check warning: {} - {}", result.check_name, result.message);
                                }
                                apt_ostree::monitoring::HealthStatus::Critical => {
                                    error!("Health check critical: {} - {}", result.check_name, result.message);
                                }
                                apt_ostree::monitoring::HealthStatus::Unknown => {
                                    warn!("Health check unknown: {} - {}", result.check_name, result.message);
                                }
                            }
                        }
                    }
                    Err(e) => {
                        error!("Failed to run health checks: {}", e);
                    }
                }
            }
        });
        
        info!("Monitoring service started successfully");
        Ok(())
    }
    
    /// Stop the monitoring service
    async fn stop(&mut self) -> AptOstreeResult<()> {
        info!("Stopping monitoring service");
        
        self.running = false;
        
        // Export final metrics
        if self.config.export_metrics {
            if let Err(e) = Self::export_metrics_to_file(&self.monitoring_manager, &self.config.metrics_file).await {
                error!("Failed to export final metrics: {}", e);
            }
        }
        
        info!("Monitoring service stopped");
        Ok(())
    }
    
    /// Export metrics to file
    async fn export_metrics_to_file(
        monitoring_manager: &Arc<MonitoringManager>,
        file_path: &str,
    ) -> AptOstreeResult<()> {
        let metrics_json = monitoring_manager.export_metrics().await?;
        
        // Ensure directory exists
        if let Some(parent) = std::path::Path::new(file_path).parent() {
            std::fs::create_dir_all(parent)?;
        }
        
        // Write metrics to file
        std::fs::write(file_path, metrics_json)?;
        
        debug!("Metrics exported to: {}", file_path);
        Ok(())
    }
    
    /// Get service statistics
    async fn get_statistics(&self) -> AptOstreeResult<String> {
        let stats = self.monitoring_manager.get_statistics().await?;
        
        let output = format!(
            "Monitoring Service Statistics:\n\
             Uptime: {} seconds\n\
             Metrics collected: {}\n\
             Performance metrics: {}\n\
             Active transactions: {}\n\
             Health checks performed: {}\n\
             Service running: {}\n",
            stats.uptime_seconds,
            stats.metrics_collected,
            stats.performance_metrics_collected,
            stats.active_transactions,
            stats.health_checks_performed,
            self.running
        );
        
        Ok(output)
    }
    
    /// Run a single health check cycle
    async fn run_health_check_cycle(&self) -> AptOstreeResult<()> {
        info!("Running health check cycle");
        
        let results = self.monitoring_manager.run_health_checks().await?;
        
        let mut healthy_count = 0;
        let mut warning_count = 0;
        let mut critical_count = 0;
        let mut unknown_count = 0;
        
        for result in results {
            match result.status {
                apt_ostree::monitoring::HealthStatus::Healthy => {
                    healthy_count += 1;
                    debug!("✅ {}: {}", result.check_name, result.message);
                }
                apt_ostree::monitoring::HealthStatus::Warning => {
                    warning_count += 1;
                    warn!("⚠️  {}: {}", result.check_name, result.message);
                }
                apt_ostree::monitoring::HealthStatus::Critical => {
                    critical_count += 1;
                    error!("❌ {}: {}", result.check_name, result.message);
                }
                apt_ostree::monitoring::HealthStatus::Unknown => {
                    unknown_count += 1;
                    warn!("❓ {}: {}", result.check_name, result.message);
                }
            }
        }
        
        info!(
            "Health check cycle completed: {} healthy, {} warnings, {} critical, {} unknown",
            healthy_count, warning_count, critical_count, unknown_count
        );
        
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    tracing_subscriber::fmt::init();
    
    info!("Starting APT-OSTree monitoring service");
    
    // Parse command line arguments
    let args: Vec<String> = std::env::args().collect();
    
    if args.len() > 1 {
        match args[1].as_str() {
            "start" => {
                let config = MonitoringServiceConfig::default();
                let mut service = MonitoringService::new(config)?;
                service.start().await?;
                
                // Keep the service running
                loop {
                    tokio::time::sleep(Duration::from_secs(1)).await;
                }
            }
            "stop" => {
                info!("Stop command received (not implemented in this version)");
            }
            "status" => {
                let config = MonitoringServiceConfig::default();
                let service = MonitoringService::new(config)?;
                let stats = service.get_statistics().await?;
                println!("{}", stats);
            }
            "health-check" => {
                let config = MonitoringServiceConfig::default();
                let service = MonitoringService::new(config)?;
                service.run_health_check_cycle().await?;
            }
            "export-metrics" => {
                let config = MonitoringServiceConfig::default();
                let service = MonitoringService::new(config)?;
                let metrics_json = service.monitoring_manager.export_metrics().await?;
                println!("{}", metrics_json);
            }
            _ => {
                eprintln!("Usage: {} [start|stop|status|health-check|export-metrics]", args[0]);
                std::process::exit(1);
            }
        }
    } else {
        // Default: start the service
        let config = MonitoringServiceConfig::default();
        let mut service = MonitoringService::new(config)?;
        service.start().await?;
        
        // Keep the service running
        loop {
            tokio::time::sleep(Duration::from_secs(1)).await;
        }
    }
    
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_monitoring_service_creation() {
        let config = MonitoringServiceConfig::default();
        let service = MonitoringService::new(config).unwrap();
        assert!(service.running == false);
    }
    
    #[tokio::test]
    async fn test_health_check_cycle() {
        let config = MonitoringServiceConfig::default();
        let service = MonitoringService::new(config).unwrap();
        assert!(service.run_health_check_cycle().await.is_ok());
    }
    
    #[tokio::test]
    async fn test_get_statistics() {
        let config = MonitoringServiceConfig::default();
        let service = MonitoringService::new(config).unwrap();
        let stats = service.get_statistics().await.unwrap();
        assert!(!stats.is_empty());
        assert!(stats.contains("Monitoring Service Statistics"));
    }
} 