//! I/O statistics sampling

/// Sample I/O statistics (I/O wait percent, queue depth)
/// Returns (io_wait_percent, queue_depth) tuple
pub fn sample_io_statistics() -> (f64, f64) {
    #[cfg(target_os = "linux")]
    {
        sample_io_statistics_linux()
    }

    #[cfg(target_os = "macos")]
    {
        sample_io_statistics_macos()
    }

    #[cfg(not(any(target_os = "linux", target_os = "macos")))]
    {
        (0.0, 0.0) // Unsupported platform
    }
}

/// Linux: Read I/O statistics from /proc/diskstats
#[cfg(target_os = "linux")]
fn sample_io_statistics_linux() -> (f64, f64) {
    use std::fs;
    use std::sync::atomic::{AtomicU64, Ordering};

    // Static variables to track delta between samples
    static LAST_IO_TIME: AtomicU64 = AtomicU64::new(0);
    static LAST_SAMPLE_TIME: AtomicU64 = AtomicU64::new(0);

    let stat_path = "/proc/diskstats";

    if let Ok(content) = fs::read_to_string(stat_path) {
        let mut total_io_time_ms = 0u64;
        let mut ios_in_progress = 0u64;

        for line in content.lines() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 14 {
                // /proc/diskstats format (kernel 4.18+):
                // major minor name rd_ios rd_merges rd_sectors rd_ticks wr_ios wr_merges wr_sectors wr_ticks ios_in_prog io_ticks io_wt
                // Index:  0     1     2      3        4           5         6      7        8          9         10         11        12     13

                // Skip partition entries (only use whole disks like sda, nvme0n1)
                let name = parts[2];
                if name
                    .chars()
                    .last()
                    .map(|c| c.is_ascii_digit())
                    .unwrap_or(false)
                    && !name.starts_with("nvme")
                {
                    continue; // Skip partitions like sda1, sda2
                }

                // io_ticks (field 12): total time spent doing I/O (ms)
                if let Ok(io_ticks) = parts[12].parse::<u64>() {
                    total_io_time_ms += io_ticks;
                }
                // ios_in_progress (field 11): I/O requests currently in flight
                if let Ok(ios) = parts[11].parse::<u64>() {
                    ios_in_progress += ios;
                }
            }
        }

        let now_ms = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .map(|d| d.as_millis() as u64)
            .unwrap_or(0);

        let last_io = LAST_IO_TIME.swap(total_io_time_ms, Ordering::Relaxed);
        let last_time = LAST_SAMPLE_TIME.swap(now_ms, Ordering::Relaxed);

        // Calculate I/O wait as percentage of wall clock time spent in I/O
        let io_wait_percent = if last_time > 0 && now_ms > last_time {
            let delta_io_ms = total_io_time_ms.saturating_sub(last_io);
            let delta_time_ms = now_ms - last_time;
            ((delta_io_ms as f64 / delta_time_ms as f64) * 100.0).min(100.0)
        } else {
            0.0 // First sample, no delta available
        };

        (io_wait_percent, ios_in_progress as f64)
    } else {
        (0.0, 0.0)
    }
}

/// macOS: Read I/O statistics using IOKit via system_profiler or iostat
#[cfg(target_os = "macos")]
fn sample_io_statistics_macos() -> (f64, f64) {
    use std::process::Command;

    // Use iostat to get disk I/O statistics
    // iostat -d -c 1 gives one sample of disk stats
    let output = Command::new("iostat").args(["-d", "-c", "1"]).output();

    match output {
        Ok(out) if out.status.success() => {
            let stdout = String::from_utf8_lossy(&out.stdout);

            // Parse iostat output - look for KB/t, tps, MB/s columns
            // The last line contains current stats
            let mut total_tps = 0.0f64; // Transactions per second (approximates queue activity)

            for line in stdout.lines().skip(2) {
                // Skip header lines
                let parts: Vec<&str> = line.split_whitespace().collect();
                if parts.len() >= 3 {
                    // Column 1 is tps (transactions per second)
                    if let Ok(tps) = parts[1].parse::<f64>() {
                        total_tps += tps;
                    }
                }
            }

            // On macOS, we can't easily get I/O wait percentage without dtrace
            // Return 0 for io_wait, use tps as approximate queue indicator
            let queue_depth = (total_tps / 1000.0).min(10.0); // Normalize to 0-10 range

            (0.0, queue_depth)
        }
        _ => (0.0, 0.0),
    }
}
