//! Disk profiler orchestrator

use std::path::Path;

use super::super::error::ProfilingError;
use super::super::logging;
use super::super::tempfile::check_disk_space;
use super::super::types::BlockSize;
use super::super::validation::validate_path;
use super::iops::measure_iops;
use super::latency::test_disk_latency;
use super::random::{measure_random_read, measure_random_write};
use super::result::DiskBenchmarkResult;
use super::sequential::{measure_sequential_read, measure_sequential_write};

/// Disk performance profiler
pub struct DiskProfiler {
    path: std::path::PathBuf,
    test_file_size: u64,
    warmup_iterations: u32,
}

impl DiskProfiler {
    /// Create disk profiler for a filesystem path
    pub fn new(path: &Path) -> Result<Self, ProfilingError> {
        validate_path(path)?;

        let available = check_disk_space(path, 2 * 1024 * 1024 * 1024)?; // 2GB

        Ok(Self {
            path: path.to_path_buf(),
            test_file_size: std::cmp::min(available / 2, 1024 * 1024 * 1024), // Max 1GB
            warmup_iterations: 1,
        })
    }

    /// Set test file size
    pub fn with_test_file_size(mut self, size: u64) -> Self {
        self.test_file_size = size;
        self
    }

    /// Set warm-up iterations
    pub fn with_warmup_iterations(mut self, iterations: u32) -> Self {
        self.warmup_iterations = iterations;
        self
    }

    /// Run full disk benchmark
    pub fn run_benchmark(&self) -> Result<DiskBenchmarkResult, ProfilingError> {
        logging::log_info(&format!(
            "Starting disk benchmark on {}",
            self.path.display()
        ));

        // Warm-up
        for i in 0..self.warmup_iterations {
            logging::log_debug(&format!("Warm-up iteration {}", i + 1));
            let _ = measure_sequential_write(&self.path, 10 * 1024 * 1024);
        }

        // Sequential benchmarks
        let sequential_read = measure_sequential_read(&self.path, self.test_file_size)?;
        let sequential_write = measure_sequential_write(&self.path, self.test_file_size)?;

        // Random benchmarks (4K blocks)
        let random_read = measure_random_read(&self.path, self.test_file_size, BlockSize::Bytes4K)?;
        let random_write =
            measure_random_write(&self.path, self.test_file_size, BlockSize::Bytes4K)?;

        // IOPS
        let iops = measure_iops(&self.path)?;

        // Latency
        let latency = test_disk_latency(&self.path)?;

        Ok(DiskBenchmarkResult {
            path: self.path.clone(),
            sequential_read,
            sequential_write,
            random_read,
            random_write,
            iops,
            latency,
        })
    }
}

/// Run full disk benchmark (convenience function)
pub fn run_disk_benchmark(path: &Path) -> Result<DiskBenchmarkResult, ProfilingError> {
    let profiler = DiskProfiler::new(path)?;
    profiler.run_benchmark()
}

/// Run disk benchmark with custom test file size
///
/// # Arguments
/// * `path` - Path to test directory
/// * `size_bytes` - Test file size in bytes
pub fn run_disk_benchmark_with_size(
    path: &Path,
    size_bytes: u64,
) -> Result<DiskBenchmarkResult, ProfilingError> {
    let profiler = DiskProfiler::new(path)?.with_test_file_size(size_bytes);
    profiler.run_benchmark()
}
