//! Performance Validation for DQN Implementation
//!
//! Validates that the DQN agent meets the critical HFT requirement of
//! <100μs inference latency for real trading decisions.

/// Performance validation configuration
#[derive(Debug, Clone)]
pub struct PerformanceValidationConfig {
    pub max_latency_us: f64,
    pub max_failure_rate: f64,
    pub min_throughput_ops: f64,
}

impl Default for PerformanceValidationConfig {
    fn default() -> Self {
        Self {
            max_latency_us: 100.0,       // 100μs max latency for HFT
            max_failure_rate: 15.0,      // 15% max failure rate
            min_throughput_ops: 10000.0, // 10k ops/sec minimum
        }
    }
}

/// Performance validation results
#[derive(Debug, Clone)]
pub struct PerformanceValidationResults {
    pub mean_latency_us: f64,
    pub p50_latency_us: f64,
    pub p95_latency_us: f64,
    pub p99_latency_us: f64,
    pub max_latency_us: f64,
    pub min_latency_us: f64,
    pub failures: usize,
    pub failure_rate: f64,
    pub passed: bool,
    pub throughput_ops_per_sec: f64,
}

/// `DQN` Performance Validator
#[derive(Debug)]
pub struct DQNPerformanceValidator {
    config: PerformanceValidationConfig,
}

impl DQNPerformanceValidator {
    /// Create new performance validator
    pub const fn new(config: PerformanceValidationConfig) -> Self {
        Self { config }
    }

    /// Calculate statistics from latency measurements
    pub fn calculate_statistics(
        &self,
        latencies: Vec<f64>,
        failures: usize,
    ) -> PerformanceValidationResults {
        let mut sorted_latencies = latencies.clone();
        sorted_latencies.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));

        let mean_latency_us = latencies.iter().sum::<f64>() / latencies.len() as f64;
        let failure_rate = (failures as f64 / latencies.len() as f64) * 100.0;

        let p50_latency_us = sorted_latencies[latencies.len() / 2];
        let p95_latency_us = sorted_latencies[(latencies.len() as f64 * 0.95) as usize];
        let p99_latency_us = sorted_latencies[(latencies.len() as f64 * 0.99) as usize];

        let passed = mean_latency_us < self.config.max_latency_us
            && failure_rate < self.config.max_failure_rate;

        PerformanceValidationResults {
            mean_latency_us,
            p50_latency_us,
            p95_latency_us,
            p99_latency_us,
            max_latency_us: sorted_latencies.last().copied().unwrap_or(0.0),
            min_latency_us: sorted_latencies.first().copied().unwrap_or(0.0),
            failures,
            failure_rate,
            passed,
            throughput_ops_per_sec: 1_000_000.0 / mean_latency_us, // Convert μs to ops/sec
        }
    }

    /// Generate performance report
    pub fn generate_report(&self, results: &PerformanceValidationResults) -> String {
        format!(
            "DQN Performance Validation Report\n\
             Status: {}\n\
             Mean Latency: {:.2}μs\n\
             P50: {:.2}μs, P95: {:.2}μs, P99: {:.2}μs\n\
             Throughput: {:.0} ops/sec\n\
             Failures: {} ({:.1}%)",
            if results.passed { "PASSED" } else { "FAILED" },
            results.mean_latency_us,
            results.p50_latency_us,
            results.p95_latency_us,
            results.p99_latency_us,
            results.throughput_ops_per_sec,
            results.failures,
            results.failure_rate
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;


    #[test]
    fn test_performance_validator_creation() {
        let config = PerformanceValidationConfig::default();
        let _validator = DQNPerformanceValidator::new(config);
    }

    #[test]
    fn test_statistics_calculation() {
        let config = PerformanceValidationConfig::default();
        let validator = DQNPerformanceValidator::new(config);

        let latencies = vec![10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0];
        let results = validator.calculate_statistics(latencies, 1);

        assert_eq!(results.mean_latency_us, 55.0);
        assert_eq!(results.failures, 1);
        assert_eq!(results.failure_rate, 10.0);
        assert!(results.passed); // 55μs mean < 100μs target, 10% < max failure rate
    }

    #[test]
    fn test_report_generation() {
        let config = PerformanceValidationConfig::default();
        let validator = DQNPerformanceValidator::new(config);

        let results = PerformanceValidationResults {
            mean_latency_us: 50.0,
            p50_latency_us: 45.0,
            p95_latency_us: 80.0,
            p99_latency_us: 95.0,
            max_latency_us: 100.0,
            min_latency_us: 30.0,
            failures: 10,
            failure_rate: 1.0,
            passed: true,
            throughput_ops_per_sec: 20000.0,
        };

        let report = validator.generate_report(&results);

        assert!(report.contains("PASSED"));
        assert!(report.contains("50.00μs"));
        assert!(report.contains("20000 ops/sec"));
    }
}
