//! Utilization report aggregation

use super::sample::UtilizationSample;

/// Utilization report with peak and average values
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct UtilizationReport {
    pub peak_cpu_percent: f64,
    pub average_cpu_percent: f64,
    pub peak_memory_percent: f64,
    pub average_memory_percent: f64,
    pub peak_memory_bytes: u64,
    pub average_memory_bytes: u64,
    pub peak_io_wait_percent: f64,
    pub average_io_wait_percent: f64,
    pub sample_count: usize,
}

impl UtilizationReport {
    /// Create report from samples
    pub fn from_samples(samples: &[UtilizationSample]) -> Self {
        if samples.is_empty() {
            return Self {
                peak_cpu_percent: 0.0,
                average_cpu_percent: 0.0,
                peak_memory_percent: 0.0,
                average_memory_percent: 0.0,
                peak_memory_bytes: 0,
                average_memory_bytes: 0,
                peak_io_wait_percent: 0.0,
                average_io_wait_percent: 0.0,
                sample_count: 0,
            };
        }

        let peak_cpu = samples
            .iter()
            .map(|s| s.cpu_percent)
            .fold(f64::NEG_INFINITY, f64::max);
        let avg_cpu = samples.iter().map(|s| s.cpu_percent).sum::<f64>() / samples.len() as f64;

        let peak_mem = samples
            .iter()
            .map(|s| s.memory_percent)
            .fold(f64::NEG_INFINITY, f64::max);
        let avg_mem = samples.iter().map(|s| s.memory_percent).sum::<f64>() / samples.len() as f64;

        let peak_mem_bytes = samples
            .iter()
            .map(|s| s.memory_used_bytes)
            .max()
            .unwrap_or(0);
        let avg_mem_bytes =
            samples.iter().map(|s| s.memory_used_bytes).sum::<u64>() / samples.len() as u64;

        let peak_io_wait = samples
            .iter()
            .map(|s| s.io_wait_percent)
            .fold(f64::NEG_INFINITY, f64::max);
        let avg_io_wait =
            samples.iter().map(|s| s.io_wait_percent).sum::<f64>() / samples.len() as f64;

        Self {
            peak_cpu_percent: peak_cpu,
            average_cpu_percent: avg_cpu,
            peak_memory_percent: peak_mem,
            average_memory_percent: avg_mem,
            peak_memory_bytes: peak_mem_bytes,
            average_memory_bytes: avg_mem_bytes,
            peak_io_wait_percent: peak_io_wait,
            average_io_wait_percent: avg_io_wait,
            sample_count: samples.len(),
        }
    }
}
