//! CPU profiler orchestrator

use super::super::error::ProfilingError;
use super::cache::measure_cache_misses;
use super::scaling::measure_multi_thread_scaling;
use super::single::measure_single_thread_performance;
use super::topology::detect_cpu_topology;

/// CPU performance profiler
///
/// Provides comprehensive CPU benchmarking including single-thread performance,
/// multi-thread scaling, and cache miss analysis.
///
/// # Example
///
/// ```rust,no_run
/// use herolib_os::profiling::cpu::CPUProfiler;
/// use std::time::Duration;
///
/// let profiler = CPUProfiler::new();
/// let result = profiler.run_benchmark(4, Duration::from_secs(30))?;
///
/// println!("Single-thread score: {}", result.single_thread.combined_score);
/// if let Some(multi) = result.multi_thread {
///     println!("Multi-thread score: {}", multi.total_score);
/// }
/// # Ok::<(), herolib_os::profiling::error::ProfilingError>(())
/// ```
pub struct CPUProfiler;

impl CPUProfiler {
    /// Create a new CPU profiler
    ///
    /// # Returns
    ///
    /// A new `CPUProfiler` instance ready to run benchmarks
    pub fn new() -> Self {
        Self
    }

    /// Run comprehensive CPU benchmark
    ///
    /// Performs single-thread and multi-thread performance tests, measures
    /// thread scaling efficiency, and analyzes cache miss rates.
    ///
    /// # Arguments
    ///
    /// * `threads` - Number of threads to use for multi-thread tests (1-256)
    /// * `_duration` - Test duration (currently unused, reserved for future use)
    ///
    /// # Returns
    ///
    /// * `Ok(CPUBenchmarkResult)` - Complete benchmark results including:
    ///   - Single-thread performance (integer, float, combined scores)
    ///   - Multi-thread performance (if system has multiple cores)
    ///   - Thread scaling efficiency
    ///   - Cache miss rates (L1, L2, L3)
    /// * `Err(ProfilingError)` - If benchmark fails
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// use herolib_os::profiling::cpu::CPUProfiler;
    /// use std::time::Duration;
    ///
    /// let profiler = CPUProfiler::new();
    /// let result = profiler.run_benchmark(8, Duration::from_secs(60))?;
    /// # Ok::<(), herolib_os::profiling::error::ProfilingError>(())
    /// ```
    pub fn run_benchmark(
        &self,
        threads: u32,
        _duration: std::time::Duration,
    ) -> Result<super::CPUBenchmarkResult, ProfilingError> {
        super::super::logging::log_info("Running CPU benchmark");

        let topology = detect_cpu_topology()?;

        // Single-thread benchmark
        let single_thread = measure_single_thread_performance()?;

        // Multi-thread benchmark (skip if single-core)
        let (multi_thread, scaling) = if topology.cores > 1 {
            let scaling_result = measure_multi_thread_scaling(threads.min(topology.cores))?;
            let multi_thread_result = super::MultiThreadResult {
                threads: scaling_result.threads,
                total_score: single_thread.combined_score * scaling_result.speedup,
                per_thread_score: single_thread.combined_score,
                duration: single_thread.duration,
            };
            (Some(multi_thread_result), Some(scaling_result))
        } else {
            super::super::logging::log_info(
                "Single-core system detected, skipping multi-thread tests",
            );
            (None, None)
        };

        // Cache misses
        let cache_misses = Some(measure_cache_misses()?);

        Ok(super::CPUBenchmarkResult {
            single_thread,
            multi_thread,
            scaling,
            cache_misses,
        })
    }
}

impl Default for CPUProfiler {
    fn default() -> Self {
        Self::new()
    }
}

/// Run CPU benchmark (convenience function)
pub fn run_cpu_benchmark(
    threads: u32,
    duration: std::time::Duration,
) -> Result<super::CPUBenchmarkResult, ProfilingError> {
    let profiler = CPUProfiler::new();
    profiler.run_benchmark(threads, duration)
}
