//! Resource utilization monitoring

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use super::super::logging;
use super::cpu::sample_cpu_utilization;
use super::io::sample_io_statistics;
use super::memory::sample_memory_usage;
use super::report::UtilizationReport;
use super::sample::UtilizationSample;

/// Resource monitor for tracking utilization during benchmarks
pub struct ResourceMonitor {
    samples: Arc<Mutex<Vec<UtilizationSample>>>,
    running: Arc<AtomicBool>,
    sample_interval: Duration,
    concurrent_warning_threshold: f64,
}

impl ResourceMonitor {
    /// Create resource monitor with configurable sample interval
    pub fn new(interval: Duration) -> Self {
        let config = super::super::config::global_config_or_default();
        Self {
            samples: Arc::new(Mutex::new(Vec::new())),
            running: Arc::new(AtomicBool::new(false)),
            sample_interval: interval,
            concurrent_warning_threshold: config.concurrent_cpu_threshold,
        }
    }

    /// Set concurrent benchmark warning threshold
    pub fn with_concurrent_threshold(mut self, threshold: f64) -> Self {
        self.concurrent_warning_threshold = threshold;
        self
    }

    /// Start monitoring in background thread
    pub fn start(&self) {
        self.running.store(true, Ordering::SeqCst);

        let samples = Arc::clone(&self.samples);
        let running = Arc::clone(&self.running);
        let interval = self.sample_interval;
        let threshold = self.concurrent_warning_threshold;

        thread::spawn(move || {
            while running.load(Ordering::SeqCst) {
                let sample = UtilizationSample {
                    timestamp: chrono::Utc::now()
                        .to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
                    cpu_percent: sample_cpu_utilization() * 100.0, // Convert fraction to percentage
                    memory_percent: sample_memory_usage().0,
                    memory_used_bytes: sample_memory_usage().1,
                    memory_total_bytes: sample_memory_usage().2,
                    io_wait_percent: sample_io_statistics().0,
                    io_queue_depth: sample_io_statistics().1,
                };

                // Check for concurrent benchmarks
                if sample.cpu_percent > threshold {
                    logging::log_warn(&format!(
                        "High CPU utilization detected ({:.1}%) - concurrent benchmark may be running",
                        sample.cpu_percent
                    ));
                }

                // Thread-safe sample collection
                if let Ok(mut samples_vec) = samples.lock() {
                    samples_vec.push(sample);
                } else {
                    logging::log_error(
                        "Failed to acquire samples lock - monitoring data may be lost",
                    );
                }

                std::thread::sleep(interval);
            }
        });
    }

    /// Stop monitoring and generate report
    pub fn stop(&self) -> UtilizationReport {
        self.running.store(false, Ordering::SeqCst);

        // Collect all samples for report generation
        let samples = if let Ok(samples_vec) = self.samples.lock() {
            samples_vec.clone()
        } else {
            logging::log_error("Failed to acquire samples lock for report generation");
            Vec::new()
        };

        UtilizationReport::from_samples(&samples)
    }

    /// Get current utilization sample
    pub fn current_sample(&self) -> UtilizationSample {
        UtilizationSample {
            timestamp: chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
            cpu_percent: sample_cpu_utilization() * 100.0, // Convert fraction to percentage
            memory_percent: sample_memory_usage().0,
            memory_used_bytes: sample_memory_usage().1,
            memory_total_bytes: sample_memory_usage().2,
            io_wait_percent: sample_io_statistics().0,
            io_queue_depth: sample_io_statistics().1,
        }
    }
}

impl Clone for ResourceMonitor {
    fn clone(&self) -> Self {
        Self {
            samples: Arc::clone(&self.samples),
            running: Arc::clone(&self.running),
            sample_interval: self.sample_interval,
            concurrent_warning_threshold: self.concurrent_warning_threshold,
        }
    }
}
