//! IOPS measurement

use std::fs::OpenOptions;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::time::Instant;

use super::super::error::ProfilingError;
use super::super::tempfile::TempFileManager;

/// IOPS measurement result
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct IOPSResult {
    pub read_iops: f64,
    pub write_iops: f64,
    pub mixed_iops: f64,
    pub block_size: u32,
}

/// Measure IOPS performance
pub fn measure_iops(path: &Path) -> Result<IOPSResult, ProfilingError> {
    super::super::logging::log_info("Measuring IOPS performance");

    let block_size = 4096;
    let size_bytes = 100 * 1024 * 1024; // 100 MB
    let num_operations = 10000;

    let mut manager = TempFileManager::new(path, "iops")?;
    let temp_path = manager.create_file(size_bytes)?;

    // Measure read IOPS
    let start = Instant::now();
    {
        let mut file = OpenOptions::new().read(true).open(&temp_path)?;
        let mut buffer = vec![0u8; block_size];
        for _ in 0..num_operations {
            let offset = rand::random::<u64>() % (size_bytes - block_size as u64);
            file.seek(SeekFrom::Start(offset))?;
            file.read(&mut buffer)?;
        }
    }
    let read_duration = start.elapsed();
    let read_iops = num_operations as f64 / read_duration.as_secs_f64();

    // Measure write IOPS
    let start = Instant::now();
    {
        let mut file = OpenOptions::new().write(true).open(&temp_path)?;
        let buffer = vec![0u8; block_size];
        for _ in 0..num_operations {
            let offset = rand::random::<u64>() % (size_bytes - block_size as u64);
            file.seek(SeekFrom::Start(offset))?;
            file.write_all(&buffer)?;
        }
        file.sync_all()?;
    }
    let write_duration = start.elapsed();
    let write_iops = num_operations as f64 / write_duration.as_secs_f64();

    // Measure mixed IOPS (70% read, 30% write)
    let start = Instant::now();
    {
        let mut file = OpenOptions::new().read(true).write(true).open(&temp_path)?;
        let mut buffer = vec![0u8; block_size];
        for i in 0..num_operations {
            let offset = rand::random::<u64>() % (size_bytes - block_size as u64);
            file.seek(SeekFrom::Start(offset))?;
            if i % 10 < 7 {
                file.read(&mut buffer)?;
            } else {
                file.write_all(&buffer)?;
            }
        }
        file.sync_all()?;
    }
    let mixed_duration = start.elapsed();
    let mixed_iops = num_operations as f64 / mixed_duration.as_secs_f64();

    Ok(IOPSResult {
        read_iops,
        write_iops,
        mixed_iops,
        block_size: block_size as u32,
    })
}
