//! Integration tests for profiling module production readiness

extern crate herolib_os;

use herolib_os::profiling;
use herolib_os::profiling::config;
use herolib_os::profiling::error::ProfilingError;
use herolib_os::profiling::logging::{log_debug, log_error, log_info, log_warn};
use herolib_os::profiling::progress;
use herolib_os::profiling::sanity::SanityChecker;
use herolib_os::profiling::tempfile::TempFileManager;
use herolib_os::profiling::validation::validate_path;
use rhai::Engine;
use std::sync::Arc;
use std::thread;

#[test]
fn test_error_handling_comprehensive() {
    // Test that all error types are properly defined
    let error = ProfilingError::MemoryError("Test error".to_string());
    assert!(matches!(error, ProfilingError::MemoryError(_)));

    let error = ProfilingError::CpuError("Test error".to_string());
    assert!(matches!(error, ProfilingError::CpuError(_)));

    let error = ProfilingError::NetworkError("Test error".to_string());
    assert!(matches!(error, ProfilingError::NetworkError(_)));

    let error = ProfilingError::InsufficientSpace {
        required: 1000,
        available: 500,
    };
    assert!(matches!(error, ProfilingError::InsufficientSpace { .. }));
}

#[test]
fn test_input_validation_security() {
    use std::path::Path;
    use tempfile::TempDir;

    // Test path traversal protection
    let malicious_path = Path::new("/tmp/../../../etc/passwd");
    assert!(validate_path(malicious_path).is_err());

    // Test valid path that exists
    let temp_dir = TempDir::new().unwrap();
    let valid_path = temp_dir.path();
    assert!(validate_path(valid_path).is_ok());
}

#[test]
fn test_sanity_checking() {
    // Test network bandwidth validation
    assert!(SanityChecker::check_network_result(1_000_000_000.0).is_ok()); // 1 Gbps
    assert!(SanityChecker::check_network_result(-1.0).is_err()); // Negative
    assert!(SanityChecker::check_network_result(0.0).is_ok()); // Zero (warning)

    // Test temperature validation
    assert!(SanityChecker::check_temperature(50.0).is_ok()); // Normal
    assert!(SanityChecker::check_temperature(-10.0).is_err()); // Negative
    assert!(SanityChecker::check_temperature(200.0).is_err()); // Too high

    // Test IOPS validation
    assert!(SanityChecker::check_iops(1000.0).is_ok()); // Normal
    assert!(SanityChecker::check_iops(-1.0).is_err()); // Negative
}

#[test]
fn test_tempfile_security() {
    use tempfile::TempDir;

    let temp_dir = TempDir::new().unwrap();
    let temp_path = temp_dir.path();

    // Test secure tempfile creation
    let mut manager = TempFileManager::new(temp_path, "test_secure").unwrap();
    let file_path = manager.create_file(1024).unwrap();

    // Verify file exists
    assert!(file_path.exists());

    // Verify cleanup
    manager.cleanup().unwrap();
    assert!(!file_path.exists());
}

#[test]
fn test_progress_reporting() {
    use std::sync::Arc;

    let callback = Arc::new(progress::NoOpProgressCallback);
    let _reporter = progress::ProgressReporter::with_default_interval(callback);

    // Test progress validation
    let update = progress::ProgressUpdate::new(50.0, "test_phase");
    assert!(update.validate().is_ok());

    // Test invalid progress - this should be clamped and still pass validation
    let invalid_update = progress::ProgressUpdate::new(-10.0, "test_phase");
    // The constructor clamps the value, so validation should pass
    assert!(invalid_update.validate().is_ok());
    assert!(invalid_update.percent == 0.0); // Should be clamped to 0

    // Test empty phase - this should fail validation
    let empty_phase_update = progress::ProgressUpdate::new(50.0, "");
    assert!(empty_phase_update.validate().is_err());
}

#[test]
fn test_rhai_security() {
    let mut engine = Engine::new();

    // Register profiling modules
    profiling::rhai::register_profiling_module(&mut engine).unwrap();

    // Test that dangerous functions are disabled
    let result = engine.eval::<()>("File::create(\"test.txt\")");
    assert!(result.is_err()); // Should fail due to security restrictions

    // Test that system profiling works
    let result = engine.eval::<()>("let profile = SystemProfile();");
    assert!(result.is_ok()); // Should work

    // Test operation limits
    let result = engine.eval::<()>("for i in 0..20000 { print(i); }");
    assert!(result.is_err()); // Should fail due to operation limit
}

#[test]
fn test_configuration_system() {
    let config = config::ProfilingConfig::default();

    // Test default values
    assert!(config.memory_stress_allocation_limit > 0);
    assert!(config.max_network_bandwidth_gbps > 0.0);
    assert!(config.max_disk_throughput_mbps > 0.0);
    assert!(config.max_memory_bandwidth_gbps > 0.0);
    assert!(config.max_cpu_score > 0.0);
    assert!(config.max_disk_iops > 0.0);

    // Test cache size detection
    let config_with_cache = config.with_detected_cache_sizes();
    assert!(config_with_cache.l1_cache_size > 0);
    assert!(config_with_cache.l2_cache_size > 0);
    // L3 cache may not exist on all systems, so we just check if it's detected
    if config_with_cache.l3_cache_size > 0 {
        println!(
            "L3 cache detected: {} bytes",
            config_with_cache.l3_cache_size
        );
    } else {
        println!("L3 cache not detected (normal for many systems)");
    }
}

#[test]
fn test_thread_safety() {
    use std::sync::Arc;
    use std::thread;

    let config = Arc::new(config::global_config_or_default());
    let handles: Vec<_> = (0..10)
        .map(|_| {
            let config = Arc::clone(&config);
            thread::spawn(move || {
                // Test concurrent access to global config
                let _ = config.memory_stress_allocation_limit;
                let _ = config.max_network_bandwidth_gbps;
            })
        })
        .collect();

    // Wait for all threads to complete
    for handle in handles {
        handle.join().unwrap();
    }

    // If we reach here, thread safety is working
    assert!(true);
}

#[test]
fn test_logging_functionality() {
    // Test utility methods
    log_debug("Debug message");
    log_info("Info message");
    log_warn("Warning message");
    log_error("Error message");

    // If we reach here, logging is working without panics
    assert!(true);
}

#[test]
fn test_full_system_benchmark_workflow() {
    // Test end-to-end benchmark workflow
    use std::time::Duration;

    // Create a comprehensive benchmark report
    let mut report = profiling::BenchmarkReport::new();

    // Add CPU benchmark result
    let cpu_result = profiling::cpu::run_cpu_benchmark(2, Duration::from_secs(1))
        .expect("CPU benchmark should work");
    report
        .add_cpu_result(cpu_result)
        .expect("Should add CPU result");

    // Add memory benchmark result
    let memory_result =
        profiling::memory::measure_memory_bandwidth().expect("Memory benchmark should work");
    report
        .add_memory_result(memory_result)
        .expect("Should add memory result");

    // Add disk benchmark result (use temp directory)
    let temp_dir = std::env::temp_dir();
    let disk_result =
        profiling::disk::run_disk_benchmark(&temp_dir).expect("Disk benchmark should work");
    report
        .add_disk_result(disk_result)
        .expect("Should add disk result");

    // Generate the report
    let json_output = report.generate_json().expect("JSON generation should work");

    // Verify the report contains expected data
    assert!(!json_output.is_empty(), "JSON output should not be empty");
    assert!(json_output.contains("cpu"), "Should contain CPU data");
    assert!(json_output.contains("memory"), "Should contain memory data");
    assert!(json_output.contains("disk"), "Should contain disk data");

    // Verify schema version
    assert!(
        json_output.contains("schema_version"),
        "Should contain schema version"
    );
}

#[test]
fn test_report_generation_pipeline() {
    // Test full report generation pipeline
    let mut report = profiling::BenchmarkReport::new();

    // Add some benchmark data
    let cpu_result = profiling::cpu::run_cpu_benchmark(1, std::time::Duration::from_millis(500))
        .expect("CPU benchmark should work");
    report
        .add_cpu_result(cpu_result)
        .expect("Should add CPU result");

    // Test all output formats
    let json_output = report.generate_json().expect("JSON generation should work");
    let text_output = report.generate_text().expect("Text generation should work");
    let html_output = report.generate_html().expect("HTML generation should work");

    // Verify all formats are non-empty
    assert!(!json_output.is_empty(), "JSON should not be empty");
    assert!(!text_output.is_empty(), "Text should not be empty");
    assert!(!html_output.is_empty(), "HTML should not be empty");

    // Verify formats are different
    assert_ne!(
        json_output, text_output,
        "JSON and text should be different"
    );
    assert_ne!(
        json_output, html_output,
        "JSON and HTML should be different"
    );
    assert_ne!(
        text_output, html_output,
        "Text and HTML should be different"
    );

    // Verify JSON is valid
    serde_json::from_str::<serde_json::Value>(&json_output).expect("JSON should be valid");
}

#[test]
fn test_concurrent_benchmarks() {
    use std::sync::Arc;
    use std::thread;
    use std::time::Duration;

    // Test that benchmarks can run concurrently without interfering
    let report = Arc::new(std::sync::Mutex::new(profiling::BenchmarkReport::new()));

    let handles: Vec<_> = (0..3)
        .map(|i| {
            let report: Arc<std::sync::Mutex<profiling::BenchmarkReport>> = Arc::clone(&report);
            thread::spawn(move || {
                // Run a quick CPU benchmark
                let cpu_result = profiling::cpu::run_cpu_benchmark(1, Duration::from_millis(200))
                    .expect("CPU benchmark should work");

                // Add result to shared report
                let mut report = report.lock().unwrap();
                report
                    .add_cpu_result(cpu_result)
                    .expect("Should add CPU result");

                println!("Thread {} completed benchmark", i);
            })
        })
        .collect();

    // Wait for all threads to complete
    for handle in handles {
        handle.join().expect("Thread should complete successfully");
    }

    // Verify report has data (the concurrent access worked without errors)
    let report = report.lock().unwrap();
    let json_output = report.generate_json().expect("JSON generation should work");

    // Should have at least one CPU result (concurrent access worked)
    assert!(
        json_output.contains("\"cpu_results\""),
        "Should contain CPU results"
    );

    // Should have results from all threads (3 results)
    assert!(
        json_output.matches("\"single_thread\"").count() >= 3,
        "Should have CPU results from all threads"
    );

    // Verify the report is valid JSON
    serde_json::from_str::<serde_json::Value>(&json_output).expect("Report should be valid JSON");
}

// ============================================================================
// PARAMETERIZED TESTS - Phase 2: High-priority parameterized tests (35 tests)
// ============================================================================

/// Test parameter matrix for CPU benchmarks
#[derive(Debug, Clone)]
struct CpuBenchmarkParams {
    threads: u32,
    duration_ms: u64,
    expected_single_thread_score_min: f64,
    expected_multi_thread_available: bool,
}

impl CpuBenchmarkParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Minimal viable configuration
            Self {
                threads: 1,
                duration_ms: 100,
                expected_single_thread_score_min: 1000.0,
                expected_multi_thread_available: false, // Single thread only
            },
            // Standard configuration
            Self {
                threads: 2,
                duration_ms: 500,
                expected_single_thread_score_min: 1000.0,
                expected_multi_thread_available: true, // Should be available on multi-core systems
            },
            // High thread count
            Self {
                threads: 4,
                duration_ms: 1000,
                expected_single_thread_score_min: 1000.0,
                expected_multi_thread_available: true, // Should be available on multi-core systems
            },
            // Extended duration
            Self {
                threads: 2,
                duration_ms: 2000,
                expected_single_thread_score_min: 1000.0,
                expected_multi_thread_available: true, // Should be available on multi-core systems
            },
            // Very short duration (stress test)
            Self {
                threads: 1,
                duration_ms: 50,
                expected_single_thread_score_min: 500.0, // Lower threshold for short test
                expected_multi_thread_available: false,
            },
        ]
    }
}

/// Parameterized test for CPU benchmarks across different configurations
#[test]
fn test_cpu_benchmark_parameterized() {
    let test_cases = CpuBenchmarkParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running CPU benchmark test case {}: threads={}, duration={}ms",
            i, params.threads, params.duration_ms
        );

        let result = profiling::cpu::run_cpu_benchmark(
            params.threads,
            std::time::Duration::from_millis(params.duration_ms),
        );

        // Test should succeed
        assert!(
            result.is_ok(),
            "CPU benchmark should succeed for threads={}, duration={}ms. Error: {:?}",
            params.threads,
            params.duration_ms,
            result.err()
        );

        let benchmark = result.unwrap();

        // Verify single-thread results always exist and meet minimum threshold
        assert!(
            benchmark.single_thread.combined_score >= params.expected_single_thread_score_min,
            "Single-thread score {} should be >= {} for threads={}, duration={}ms",
            benchmark.single_thread.combined_score,
            params.expected_single_thread_score_min,
            params.threads,
            params.duration_ms
        );

        assert!(
            benchmark.single_thread.integer_score > 0.0,
            "Integer score should be positive"
        );
        assert!(
            benchmark.single_thread.float_score > 0.0,
            "Float score should be positive"
        );

        // Verify multi-thread results availability based on configuration
        if params.expected_multi_thread_available && params.threads > 1 {
            assert!(
                benchmark.multi_thread.is_some(),
                "Multi-thread results should be available for threads={}",
                params.threads
            );

            if let Some(ref multi) = benchmark.multi_thread {
                assert_eq!(
                    multi.threads, params.threads,
                    "Multi-thread result should report correct thread count"
                );
                assert!(
                    multi.total_score > 0.0,
                    "Multi-thread total score should be positive"
                );
                assert!(
                    multi.per_thread_score > 0.0,
                    "Multi-thread per-thread score should be positive"
                );
            }
        }

        // Verify scaling results when multi-thread is available
        if benchmark.multi_thread.is_some() {
            assert!(
                benchmark.scaling.is_some(),
                "Scaling results should be available when multi-thread results exist"
            );

            if let Some(ref scaling) = benchmark.scaling {
                assert!(
                    scaling.threads > 0,
                    "Scaling thread count should be positive"
                );
                assert!(scaling.speedup > 0.0, "Speedup should be positive");
                assert!(
                    scaling.ideal_speedup > 0.0,
                    "Ideal speedup should be positive"
                );
                assert!(
                    scaling.scaling_efficiency >= 0.0 && scaling.scaling_efficiency <= 10.0,
                    "Scaling efficiency should be reasonable (0-10x), got: {}",
                    scaling.scaling_efficiency
                );
            }
        }

        println!("✓ Test case {} passed", i);
    }
}

/// Test parameter matrix for workload parameters
#[derive(Debug, Clone)]
struct WorkloadParams {
    iterations: u64,
    matrix_size: usize,
    expected_min_ops_per_sec: f64,
}

impl WorkloadParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Minimal workload
            Self {
                iterations: 10_000,
                matrix_size: 10,
                expected_min_ops_per_sec: 100.0,
            },
            // Light workload
            Self {
                iterations: 100_000,
                matrix_size: 50,
                expected_min_ops_per_sec: 500.0,
            },
            // Standard workload
            Self {
                iterations: 1_000_000,
                matrix_size: 100,
                expected_min_ops_per_sec: 1000.0,
            },
            // Heavy workload
            Self {
                iterations: 5_000_000,
                matrix_size: 200,
                expected_min_ops_per_sec: 2000.0,
            },
        ]
    }
}

/// Parameterized test for CPU workloads
#[test]
fn test_cpu_workloads_parameterized() {
    let test_cases = WorkloadParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running workload test case {}: iterations={}, matrix_size={}",
            i, params.iterations, params.matrix_size
        );

        // Test instruction throughput (includes prime sieve and matrix ops internally)
        let throughput_result = profiling::cpu::workloads::test_instruction_throughput();
        assert!(
            throughput_result.is_ok(),
            "Instruction throughput test should succeed"
        );

        let throughput = throughput_result.unwrap();
        assert!(
            throughput.integer_ops_per_sec >= params.expected_min_ops_per_sec,
            "Integer ops/sec {} should be >= {}",
            throughput.integer_ops_per_sec,
            params.expected_min_ops_per_sec
        );
        assert!(
            throughput.float_ops_per_sec >= params.expected_min_ops_per_sec,
            "Float ops/sec {} should be >= {}",
            throughput.float_ops_per_sec,
            params.expected_min_ops_per_sec
        );

        // SIMD may not be available on all platforms
        if let Some(simd_ops) = throughput.simd_ops_per_sec {
            assert!(simd_ops > 0.0, "SIMD ops should be positive if available");
        }

        println!("✓ Workload test case {} passed", i);
    }
}

/// Test parameter matrix for scaling analysis
#[derive(Debug, Clone)]
struct ScalingParams {
    threads: u32,
    expected_min_efficiency: f64,
    expected_max_efficiency: f64,
}

impl ScalingParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Single thread (no scaling)
            Self {
                threads: 1,
                expected_min_efficiency: 0.0,
                expected_max_efficiency: 2.0, // Allow some measurement noise
            },
            // Dual thread
            Self {
                threads: 2,
                expected_min_efficiency: 0.3, // 30% minimum efficiency
                expected_max_efficiency: 2.0, // Allow some overhead
            },
            // Quad thread
            Self {
                threads: 4,
                expected_min_efficiency: 0.2, // 20% minimum efficiency
                expected_max_efficiency: 4.5, // Allow some overhead
            },
        ]
    }
}

/// Parameterized test for multi-thread scaling
#[test]
fn test_multi_thread_scaling_parameterized() {
    let test_cases = ScalingParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running scaling test case {}: threads={}",
            i, params.threads
        );

        let result = profiling::cpu::measure_multi_thread_scaling(params.threads);

        // Scaling test should succeed
        assert!(
            result.is_ok(),
            "Multi-thread scaling should succeed for threads={}. Error: {:?}",
            params.threads,
            result.err()
        );

        let scaling = result.unwrap();

        assert_eq!(
            scaling.threads, params.threads,
            "Scaling result should report correct thread count"
        );
        assert!(scaling.speedup > 0.0, "Speedup should be positive");
        assert!(
            scaling.ideal_speedup > 0.0,
            "Ideal speedup should be positive"
        );
        assert_eq!(
            scaling.ideal_speedup, params.threads as f64,
            "Ideal speedup should equal thread count"
        );

        // Check efficiency is within expected bounds
        assert!(
            scaling.scaling_efficiency >= params.expected_min_efficiency,
            "Scaling efficiency {} should be >= {} for threads={}",
            scaling.scaling_efficiency,
            params.expected_min_efficiency,
            params.threads
        );
        assert!(
            scaling.scaling_efficiency <= params.expected_max_efficiency,
            "Scaling efficiency {} should be <= {} for threads={}",
            scaling.scaling_efficiency,
            params.expected_max_efficiency,
            params.threads
        );

        println!(
            "✓ Scaling test case {} passed: efficiency={:.2}x",
            i, scaling.scaling_efficiency
        );
    }
}

/// Test parameter matrix for error handling
#[derive(Debug, Clone)]
struct ErrorTestParams {
    threads: u32,
    duration_ms: u64,
    should_succeed: bool,
    error_type: Option<&'static str>,
}

impl ErrorTestParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Valid cases
            Self {
                threads: 1,
                duration_ms: 100,
                should_succeed: true,
                error_type: None,
            },
            Self {
                threads: 2,
                duration_ms: 500,
                should_succeed: true,
                error_type: None,
            },
            // Edge cases that should now fail (validation)
            Self {
                threads: 0, // Should fail validation
                duration_ms: 100,
                should_succeed: false, // Should fail with validation error
                error_type: Some("validation"),
            },
            Self {
                threads: 1,
                duration_ms: 0,       // Should be handled gracefully
                should_succeed: true, // Should use minimum duration
                error_type: None,
            },
            // Extreme cases (may fail)
            Self {
                threads: 1000, // Very high thread count
                duration_ms: 100,
                should_succeed: false, // May fail due to resource limits
                error_type: Some("resource"),
            },
            Self {
                threads: 1,
                duration_ms: 10000,    // Very long duration
                should_succeed: false, // May timeout
                error_type: Some("timeout"),
            },
        ]
    }
}

/// Parameterized test for error handling and edge cases
#[test]
fn test_error_handling_parameterized() {
    let test_cases = ErrorTestParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running error test case {}: threads={}, duration={}ms, should_succeed={}, error_type={:?}",
            i, params.threads, params.duration_ms, params.should_succeed, params.error_type
        );

        let result = profiling::cpu::run_cpu_benchmark(
            params.threads,
            std::time::Duration::from_millis(params.duration_ms),
        );

        if params.should_succeed {
            assert!(
                result.is_ok(),
                "Test case {} should succeed. Error: {:?}",
                i,
                result.err()
            );
            println!("✓ Error test case {} passed (succeeded as expected)", i);
        } else {
            // May succeed or fail depending on system resources
            if result.is_err() {
                println!("✓ Error test case {} passed (failed as expected)", i);
            } else {
                println!(
                    "⚠ Error test case {} succeeded (system handled extreme case)",
                    i
                );
            }
        }
    }
}

/// Test parameter matrix for sanity checking
#[derive(Debug, Clone)]
struct SanityTestParams {
    cpu_score: f64,
    network_bandwidth: f64,
    temperature: f64,
    iops: f64,
    should_pass: bool,
}

impl SanityTestParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Valid cases
            Self {
                cpu_score: 1000000.0,
                network_bandwidth: 1000000000.0, // 1 Gbps
                temperature: 50.0,
                iops: 1000.0,
                should_pass: true,
            },
            // Edge cases that should pass (zero values are allowed by sanity checker)
            Self {
                cpu_score: 0.0,         // Zero is allowed (with warning)
                network_bandwidth: 0.0, // Zero is allowed (with warning)
                temperature: 0.0,       // Zero is allowed (with warning)
                iops: 0.0,              // Zero is allowed (with warning)
                should_pass: true,      // Should pass since zero values are allowed
            },
            // Invalid cases
            Self {
                cpu_score: -1.0,         // Negative - should fail
                network_bandwidth: -1.0, // Negative - should fail
                temperature: -10.0,      // Negative - should fail
                iops: -1.0,              // Negative - should fail
                should_pass: false,
            },
            // Extreme values
            Self {
                cpu_score: f64::MAX,
                network_bandwidth: f64::MAX,
                temperature: 200.0, // Too high - should fail
                iops: f64::MAX,
                should_pass: false,
            },
        ]
    }
}

/// Parameterized test for sanity checking
#[test]
fn test_sanity_checking_parameterized() {
    let test_cases = SanityTestParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running sanity test case {}: cpu={}, network={}, temp={}, iops={}, should_pass={}",
            i,
            params.cpu_score,
            params.network_bandwidth,
            params.temperature,
            params.iops,
            params.should_pass
        );

        // Test CPU score sanity
        let cpu_result = SanityChecker::check_cpu_result(params.cpu_score);
        if params.cpu_score >= 0.0 && params.cpu_score < 1e15 {
            assert!(
                cpu_result.is_ok(),
                "CPU score {} should pass sanity check",
                params.cpu_score
            );
        } else {
            assert!(
                cpu_result.is_err(),
                "CPU score {} should fail sanity check",
                params.cpu_score
            );
        }

        // Test network bandwidth sanity
        let network_result = SanityChecker::check_network_result(params.network_bandwidth);
        if params.network_bandwidth >= 0.0 && params.network_bandwidth < 1e15 {
            assert!(
                network_result.is_ok(),
                "Network bandwidth {} should pass sanity check",
                params.network_bandwidth
            );
        } else {
            assert!(
                network_result.is_err(),
                "Network bandwidth {} should fail sanity check",
                params.network_bandwidth
            );
        }

        // Test temperature sanity
        let temp_result = SanityChecker::check_temperature(params.temperature);
        if params.temperature >= 0.0 && params.temperature <= 150.0 {
            assert!(
                temp_result.is_ok(),
                "Temperature {} should pass sanity check",
                params.temperature
            );
        } else {
            assert!(
                temp_result.is_err(),
                "Temperature {} should fail sanity check",
                params.temperature
            );
        }

        // Test IOPS sanity
        let iops_result = SanityChecker::check_iops(params.iops);
        if params.iops >= 0.0 && params.iops < 1e10 {
            assert!(
                iops_result.is_ok(),
                "IOPS {} should pass sanity check",
                params.iops
            );
        } else {
            assert!(
                iops_result.is_err(),
                "IOPS {} should fail sanity check",
                params.iops
            );
        }

        // Validate overall expectation using should_pass field
        let overall_result = cpu_result.is_ok()
            && SanityChecker::check_network_result(params.network_bandwidth).is_ok()
            && temp_result.is_ok()
            && iops_result.is_ok();

        if params.should_pass {
            assert!(
                overall_result,
                "Sanity test case {} should pass overall but failed",
                i
            );
        } else {
            assert!(
                !overall_result,
                "Sanity test case {} should fail overall but passed",
                i
            );
        }

        println!("✓ Sanity test case {} passed", i);
    }
}

/// Test parameter matrix for concurrent benchmark scenarios
#[derive(Debug, Clone)]
struct ConcurrentTestParams {
    num_threads: u32,
    benchmark_threads: u32,
    duration_ms: u64,
    expected_min_results: usize,
}

impl ConcurrentTestParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Light concurrent load
            Self {
                num_threads: 2,
                benchmark_threads: 1,
                duration_ms: 100,
                expected_min_results: 2,
            },
            // Medium concurrent load
            Self {
                num_threads: 4,
                benchmark_threads: 2,
                duration_ms: 200,
                expected_min_results: 4,
            },
            // High concurrent load
            Self {
                num_threads: 8,
                benchmark_threads: 4,
                duration_ms: 300,
                expected_min_results: 8,
            },
        ]
    }
}

/// Parameterized test for concurrent benchmark execution
#[test]
fn test_concurrent_benchmarks_parameterized() {
    let test_cases = ConcurrentTestParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running concurrent test case {}: threads={}, benchmark_threads={}, duration={}ms",
            i, params.num_threads, params.benchmark_threads, params.duration_ms
        );

        let report = Arc::new(std::sync::Mutex::new(profiling::BenchmarkReport::new()));

        let handles: Vec<_> = (0..params.num_threads)
            .map(|thread_id| {
                let report: Arc<std::sync::Mutex<profiling::BenchmarkReport>> = Arc::clone(&report);
                let benchmark_threads = params.benchmark_threads;
                let duration = std::time::Duration::from_millis(params.duration_ms);

                thread::spawn(move || {
                    let cpu_result = profiling::cpu::run_cpu_benchmark(benchmark_threads, duration)
                        .expect("CPU benchmark should work");

                    let mut report = report.lock().unwrap();
                    report
                        .add_cpu_result(cpu_result)
                        .expect("Should add CPU result");

                    thread_id
                })
            })
            .collect();

        // Wait for all threads to complete
        let completed_threads: Vec<_> = handles
            .into_iter()
            .map(|handle| handle.join().expect("Thread should complete successfully"))
            .collect();

        // Verify all threads completed
        assert_eq!(
            completed_threads.len(),
            params.num_threads as usize,
            "All threads should complete"
        );

        // Verify report has expected number of results
        let report = report.lock().unwrap();
        let json_output = report.generate_json().expect("JSON generation should work");

        // Count CPU results in JSON
        let cpu_result_count = json_output.matches("\"single_thread\"").count();
        assert!(
            cpu_result_count >= params.expected_min_results,
            "Should have at least {} CPU results, got {}",
            params.expected_min_results,
            cpu_result_count
        );

        // Verify the report is valid JSON
        serde_json::from_str::<serde_json::Value>(&json_output)
            .expect("Report should be valid JSON");

        println!(
            "✓ Concurrent test case {} passed: {} results",
            i, cpu_result_count
        );
    }
}

/// Test parameter matrix for report generation scenarios
#[derive(Debug, Clone)]
struct ReportTestParams {
    num_cpu_results: usize,
    num_memory_results: usize,
    num_disk_results: usize,
    include_system_profile: bool,
    expected_json_size_min: usize,
}

impl ReportTestParams {
    fn test_cases() -> Vec<Self> {
        vec![
            // Minimal report
            Self {
                num_cpu_results: 1,
                num_memory_results: 0,
                num_disk_results: 0,
                include_system_profile: false,
                expected_json_size_min: 100,
            },
            // CPU only report
            Self {
                num_cpu_results: 3,
                num_memory_results: 0,
                num_disk_results: 0,
                include_system_profile: true,
                expected_json_size_min: 500,
            },
            // Mixed report
            Self {
                num_cpu_results: 2,
                num_memory_results: 2,
                num_disk_results: 2,
                include_system_profile: true,
                expected_json_size_min: 1000,
            },
            // Comprehensive report
            Self {
                num_cpu_results: 5,
                num_memory_results: 3,
                num_disk_results: 3,
                include_system_profile: true,
                expected_json_size_min: 2000,
            },
        ]
    }
}

/// Parameterized test for report generation
#[test]
fn test_report_generation_parameterized() {
    let test_cases = ReportTestParams::test_cases();

    for (i, params) in test_cases.iter().enumerate() {
        println!(
            "Running report test case {}: cpu={}, memory={}, disk={}, profile={}",
            i,
            params.num_cpu_results,
            params.num_memory_results,
            params.num_disk_results,
            params.include_system_profile
        );

        let mut report = profiling::BenchmarkReport::new();

        // Add CPU results
        for _ in 0..params.num_cpu_results {
            let cpu_result =
                profiling::cpu::run_cpu_benchmark(1, std::time::Duration::from_millis(100))
                    .expect("CPU benchmark should work");
            report
                .add_cpu_result(cpu_result)
                .expect("Should add CPU result");
        }

        // Add memory results
        for _ in 0..params.num_memory_results {
            let memory_result = profiling::memory::measure_memory_bandwidth()
                .expect("Memory benchmark should work");
            report
                .add_memory_result(memory_result)
                .expect("Should add memory result");
        }

        // Add disk results
        for _ in 0..params.num_disk_results {
            let temp_dir = std::env::temp_dir();
            let disk_result =
                profiling::disk::run_disk_benchmark(&temp_dir).expect("Disk benchmark should work");
            report
                .add_disk_result(disk_result)
                .expect("Should add disk result");
        }

        // Add system profile if requested
        if params.include_system_profile {
            let system_profile =
                profiling::system::SystemProfile::detect().expect("System profile should work");
            report.set_system_profile(system_profile);
        }

        // Test all output formats
        let json_output = report.generate_json().expect("JSON generation should work");
        let text_output = report.generate_text().expect("Text generation should work");
        let html_output = report.generate_html().expect("HTML generation should work");

        // Verify output sizes
        assert!(
            json_output.len() >= params.expected_json_size_min,
            "JSON output size {} should be >= {}",
            json_output.len(),
            params.expected_json_size_min
        );
        assert!(!text_output.is_empty(), "Text output should not be empty");
        assert!(!html_output.is_empty(), "HTML output should not be empty");

        // Verify formats are different
        assert_ne!(
            json_output, text_output,
            "JSON and text should be different"
        );
        assert_ne!(
            json_output, html_output,
            "JSON and HTML should be different"
        );
        assert_ne!(
            text_output, html_output,
            "Text and HTML should be different"
        );

        // Verify JSON is valid
        serde_json::from_str::<serde_json::Value>(&json_output).expect("JSON should be valid");

        // Verify expected content
        if params.num_cpu_results > 0 {
            assert!(
                json_output.contains("cpu_results"),
                "Should contain CPU results"
            );
        }
        if params.num_memory_results > 0 {
            assert!(
                json_output.contains("memory_results"),
                "Should contain memory results"
            );
        }
        if params.num_disk_results > 0 {
            assert!(
                json_output.contains("disk_results"),
                "Should contain disk results"
            );
        }
        if params.include_system_profile {
            assert!(
                json_output.contains("system_profile"),
                "Should contain system profile"
            );
        }

        println!(
            "✓ Report test case {} passed: JSON size={}, Text size={}, HTML size={}",
            i,
            json_output.len(),
            text_output.len(),
            html_output.len()
        );
    }
}
