//! Performance Tests for Kill Switch System
//!
//! Validates regulatory compliance requirements:
//! - Sub-100ms emergency shutdown response time
//! - Sub-1μs atomic gate checking latency
//! - Unix socket response under 50ms
//! - Signal-based shutdown under 10ms

use std::sync::Arc;
use std::time::{Duration, Instant};

use tokio::time::timeout;
use tracing::{error, info, warn};

use super::{KillSwitchConfig, TradingGate};
use super::kill_switch::{AtomicKillSwitch, UnixSocketKillSwitch};
use crate::error::RiskResult;
use crate::risk_types::KillSwitchScope;

/// Performance test results for regulatory validation
#[derive(Debug, Clone)]
pub struct KillSwitchPerformanceReport {
    pub gate_check_latency_ns: PerformanceMetrics,
    pub emergency_shutdown_latency_ms: PerformanceMetrics,
    pub unix_socket_latency_ms: PerformanceMetrics,
    pub signal_handler_latency_ms: PerformanceMetrics,
    pub redis_broadcast_latency_ms: PerformanceMetrics,
    pub regulatory_compliance: RegulatoryCompliance,
}

/// Performance metrics for each test category
#[derive(Debug, Clone)]
pub struct PerformanceMetrics {
    pub min: f64,
    pub max: f64,
    pub avg: f64,
    pub p95: f64,
    pub p99: f64,
    pub samples: u64,
}

/// Regulatory compliance assessment
#[derive(Debug, Clone)]
pub struct RegulatoryCompliance {
    pub gate_check_compliant: bool,         // <1μs
    pub emergency_shutdown_compliant: bool, // <100ms
    pub unix_socket_compliant: bool,        // <50ms
    pub signal_handler_compliant: bool,     // <10ms
    pub overall_compliant: bool,
}

/// Kill switch performance validator for regulatory compliance
pub struct KillSwitchPerformanceTester {
    kill_switch: Arc<AtomicKillSwitch>,
    trading_gate: Arc<TradingGate>,
    unix_socket: Option<UnixSocketKillSwitch>,
}

impl KillSwitchPerformanceTester {
    /// Create new performance tester
    pub async fn new() -> RiskResult<Self> {
        let config = KillSwitchConfig {
            enabled: true,
            global_channel: "test:global".to_owned(),
            strategy_channel_prefix: "test:strategy".to_owned(),
            symbol_channel_prefix: "test:symbol".to_owned(),
            auto_recovery_enabled: false, // Disable for testing
            auto_recovery_delay: Duration::from_secs(300),
        };

        let kill_switch =
            Arc::new(AtomicKillSwitch::new(config, "redis://localhost:6379".to_owned()).await?);

        let trading_gate = Arc::new(TradingGate::new(Arc::clone(&kill_switch)));

        Ok(Self {
            kill_switch,
            trading_gate,
            unix_socket: None,
        })
    }

    /// Run comprehensive performance validation for regulatory compliance
    pub async fn validate_regulatory_performance(
        &mut self,
    ) -> RiskResult<KillSwitchPerformanceReport> {
        info!("\u{1f680} Starting kill switch regulatory performance validation");

        // 1. Test atomic gate checking performance
        info!("Testing atomic gate checking latency...");
        let gate_metrics = self.test_gate_check_performance(10000).await?;

        // 2. Test emergency shutdown performance
        info!("Testing emergency shutdown latency...");
        let shutdown_metrics = self.test_emergency_shutdown_performance(100).await?;

        // 3. Test Unix socket response time
        info!("Testing Unix socket response latency...");
        let socket_metrics = self.test_unix_socket_performance(1000).await?;

        // 4. Test signal handler response time
        info!("Testing signal handler latency...");
        let signal_metrics = self.test_signal_handler_performance(100).await?;

        // 5. Test Redis broadcast latency
        info!("Testing Redis broadcast latency...");
        let redis_metrics = self.test_redis_broadcast_performance(1000).await?;

        // Assess regulatory compliance
        let compliance = RegulatoryCompliance {
            gate_check_compliant: gate_metrics.p99 < 1000.0, // <1μs (1000ns)
            emergency_shutdown_compliant: shutdown_metrics.p99 < 100.0, // <100ms
            unix_socket_compliant: socket_metrics.p99 < 50.0, // <50ms
            signal_handler_compliant: signal_metrics.p99 < 10.0, // <10ms
            overall_compliant: true,                         // Will be updated below
        };

        let compliance = RegulatoryCompliance {
            overall_compliant: compliance.gate_check_compliant
                && compliance.emergency_shutdown_compliant
                && compliance.unix_socket_compliant
                && compliance.signal_handler_compliant,
            ..compliance
        };

        let report = KillSwitchPerformanceReport {
            gate_check_latency_ns: gate_metrics,
            emergency_shutdown_latency_ms: shutdown_metrics,
            unix_socket_latency_ms: socket_metrics,
            signal_handler_latency_ms: signal_metrics,
            redis_broadcast_latency_ms: redis_metrics,
            regulatory_compliance: compliance,
        };

        self.log_performance_report(&report).await;
        Ok(report)
    }

    /// Test atomic gate checking performance (target: <1μs)
    async fn test_gate_check_performance(
        &self,
        iterations: usize,
    ) -> RiskResult<PerformanceMetrics> {
        let mut latencies = Vec::with_capacity(iterations);
        let scope = KillSwitchScope::Symbol("AAPL".to_owned());

        for _ in 0..iterations {
            let start = Instant::now();
            let _ = self.trading_gate.check_trading_allowed(&scope);
            let elapsed_ns = start.elapsed().as_nanos() as f64;
            latencies.push(elapsed_ns);
        }

        Ok(Self::calculate_metrics(latencies))
    }

    /// Test emergency shutdown performance (target: <100ms)
    async fn test_emergency_shutdown_performance(
        &self,
        iterations: usize,
    ) -> RiskResult<PerformanceMetrics> {
        let mut latencies = Vec::with_capacity(iterations);

        for i in 0..iterations {
            let start = Instant::now();

            // Activate kill switch
            self.kill_switch
                .activate(
                    KillSwitchScope::Symbol(format!("TEST{i}")),
                    "Performance test".to_owned(),
                )
                .await?;

            let elapsed_ms = start.elapsed().as_millis() as f64;
            latencies.push(elapsed_ms);

            // Deactivate for next test
            self.kill_switch
                .deactivate(
                    KillSwitchScope::Symbol(format!("TEST{i}")),
                    "test".to_owned(),
                )
                .await?;
        }

        Ok(Self::calculate_metrics(latencies))
    }

    /// Test Unix socket response performance (target: <50ms)
    async fn test_unix_socket_performance(
        &mut self,
        iterations: usize,
    ) -> RiskResult<PerformanceMetrics> {
        // Setup temporary Unix socket for testing
        let socket_path = "/tmp/test_kill_switch.sock".to_owned();
        let mut unix_socket =
            UnixSocketKillSwitch::new(socket_path.clone(), Arc::clone(&self.kill_switch)).await?;

        unix_socket.start_listener().await?;

        // Give socket time to start
        tokio::time::sleep(Duration::from_millis(100)).await;

        let mut latencies = Vec::with_capacity(iterations);

        for _ in 0..iterations {
            let start = Instant::now();

            // Test status command
            let result = timeout(
                Duration::from_millis(100),
                UnixSocketKillSwitch::quick_status_check(&socket_path, "test_auth_token".to_string()),
            )
            .await;

            let elapsed_ms = start.elapsed().as_millis() as f64;

            if result.is_ok() {
                latencies.push(elapsed_ms);
            } else {
                warn!("Unix socket request timed out or failed");
                latencies.push(100.0); // Timeout penalty
            }
        }

        // Cleanup
        let _ = unix_socket.stop_listener().await;
        let _ = std::fs::remove_file(&socket_path);

        Ok(Self::calculate_metrics(latencies))
    }

    /// Test signal handler performance (target: <10ms)
    async fn test_signal_handler_performance(
        &self,
        iterations: usize,
    ) -> RiskResult<PerformanceMetrics> {
        let mut latencies = Vec::with_capacity(iterations);

        for i in 0..iterations {
            let start = Instant::now();

            // Simulate signal-based activation (direct API call)
            self.kill_switch
                .engage(
                    KillSwitchScope::Symbol(format!("SIG{i}")),
                    "Signal test".to_owned(),
                    "signal-handler".to_owned(),
                    true, // cascade
                )
                .await?;

            let elapsed_ms = start.elapsed().as_millis() as f64;
            latencies.push(elapsed_ms);

            // Cleanup
            self.kill_switch
                .deactivate(
                    KillSwitchScope::Symbol(format!("SIG{i}")),
                    "test".to_owned(),
                )
                .await?;
        }

        Ok(Self::calculate_metrics(latencies))
    }

    /// Test Redis broadcast performance
    async fn test_redis_broadcast_performance(
        &self,
        iterations: usize,
    ) -> RiskResult<PerformanceMetrics> {
        let mut latencies = Vec::with_capacity(iterations);

        for i in 0..iterations {
            let start = Instant::now();

            // This will include Redis broadcast internally
            self.kill_switch
                .activate(
                    KillSwitchScope::Symbol(format!("REDIS{i}")),
                    "Redis test".to_owned(),
                )
                .await?;

            let elapsed_ms = start.elapsed().as_millis() as f64;
            latencies.push(elapsed_ms);

            // Cleanup
            self.kill_switch
                .deactivate(
                    KillSwitchScope::Symbol(format!("REDIS{i}")),
                    "test".to_owned(),
                )
                .await?;
        }

        Ok(Self::calculate_metrics(latencies))
    }

    /// Calculate performance metrics from latency samples
    fn calculate_metrics(mut latencies: Vec<f64>) -> PerformanceMetrics {
        if latencies.is_empty() {
            return PerformanceMetrics {
                min: 0.0,
                max: 0.0,
                avg: 0.0,
                p95: 0.0,
                p99: 0.0,
                samples: 0,
            };
        }

        latencies.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));

        let len = latencies.len();
        let min = latencies[0];
        let max = latencies[len - 1];
        let avg = latencies.iter().sum::<f64>() / len as f64;
        let p95_idx = (len as f64 * 0.95) as usize;
        let p99_idx = (len as f64 * 0.99) as usize;
        let p95 = latencies[p95_idx.min(len - 1)];
        let p99 = latencies[p99_idx.min(len - 1)];

        PerformanceMetrics {
            min,
            max,
            avg,
            p95,
            p99,
            samples: len as u64,
        }
    }

    /// Log comprehensive performance report
    async fn log_performance_report(&self, report: &KillSwitchPerformanceReport) {
        info!("\u{1f4ca} KILL SWITCH REGULATORY PERFORMANCE REPORT");
        info!("============================================");

        info!("\u{26a1} Gate Check Performance (target: <1\u{3bc}s):");
        info!(
            "   Min: {:.0}ns | Max: {:.0}ns | Avg: {:.0}ns",
            report.gate_check_latency_ns.min,
            report.gate_check_latency_ns.max,
            report.gate_check_latency_ns.avg
        );
        info!(
            "   P95: {:.0}ns | P99: {:.0}ns | Compliant: {}",
            report.gate_check_latency_ns.p95,
            report.gate_check_latency_ns.p99,
            if report.regulatory_compliance.gate_check_compliant {
                "\u{2705}"
            } else {
                "\u{274c}"
            }
        );

        info!("\u{1f6a8} Emergency Shutdown Performance (target: <100ms):");
        info!(
            "   Min: {:.1}ms | Max: {:.1}ms | Avg: {:.1}ms",
            report.emergency_shutdown_latency_ms.min,
            report.emergency_shutdown_latency_ms.max,
            report.emergency_shutdown_latency_ms.avg
        );
        info!(
            "   P95: {:.1}ms | P99: {:.1}ms | Compliant: {}",
            report.emergency_shutdown_latency_ms.p95,
            report.emergency_shutdown_latency_ms.p99,
            if report.regulatory_compliance.emergency_shutdown_compliant {
                "\u{2705}"
            } else {
                "\u{274c}"
            }
        );

        info!("\u{1f50c} Unix Socket Performance (target: <50ms):");
        info!(
            "   Min: {:.1}ms | Max: {:.1}ms | Avg: {:.1}ms",
            report.unix_socket_latency_ms.min,
            report.unix_socket_latency_ms.max,
            report.unix_socket_latency_ms.avg
        );
        info!(
            "   P95: {:.1}ms | P99: {:.1}ms | Compliant: {}",
            report.unix_socket_latency_ms.p95,
            report.unix_socket_latency_ms.p99,
            if report.regulatory_compliance.unix_socket_compliant {
                "\u{2705}"
            } else {
                "\u{274c}"
            }
        );

        info!("\u{1f4e1} Signal Handler Performance (target: <10ms):");
        info!(
            "   Min: {:.1}ms | Max: {:.1}ms | Avg: {:.1}ms",
            report.signal_handler_latency_ms.min,
            report.signal_handler_latency_ms.max,
            report.signal_handler_latency_ms.avg
        );
        info!(
            "   P95: {:.1}ms | P99: {:.1}ms | Compliant: {}",
            report.signal_handler_latency_ms.p95,
            report.signal_handler_latency_ms.p99,
            if report.regulatory_compliance.signal_handler_compliant {
                "\u{2705}"
            } else {
                "\u{274c}"
            }
        );

        info!("\u{1f4fa} Redis Broadcast Performance:");
        info!(
            "   Min: {:.1}ms | Max: {:.1}ms | Avg: {:.1}ms",
            report.redis_broadcast_latency_ms.min,
            report.redis_broadcast_latency_ms.max,
            report.redis_broadcast_latency_ms.avg
        );
        info!(
            "   P95: {:.1}ms | P99: {:.1}ms",
            report.redis_broadcast_latency_ms.p95, report.redis_broadcast_latency_ms.p99
        );

        info!("\u{1f3db}\u{fe0f} REGULATORY COMPLIANCE ASSESSMENT:");
        if report.regulatory_compliance.overall_compliant {
            info!("   \u{2705} FULLY COMPLIANT - All performance targets met");
        } else {
            error!("   \u{274c} NON-COMPLIANT - Performance targets not met");
            if !report.regulatory_compliance.gate_check_compliant {
                error!("      - Gate check latency exceeds 1\u{3bc}s");
            }
            if !report.regulatory_compliance.emergency_shutdown_compliant {
                error!("      - Emergency shutdown exceeds 100ms");
            }
            if !report.regulatory_compliance.unix_socket_compliant {
                error!("      - Unix socket response exceeds 50ms");
            }
            if !report.regulatory_compliance.signal_handler_compliant {
                error!("      - Signal handler response exceeds 10ms");
            }
        }
    }
}

/// High-frequency gate performance test for production validation
pub async fn run_hft_gate_performance_test(iterations: u64) -> RiskResult<()> {
    let config = KillSwitchConfig::default();
    let kill_switch =
        Arc::new(AtomicKillSwitch::new(config, "redis://localhost:6379".to_owned()).await?);
    let gate = TradingGate::new(kill_switch);

    let scope = KillSwitchScope::Symbol("AAPL".to_owned());
    let start_time = Instant::now();
    let mut max_latency_ns = 0_u64;
    let mut total_latency_ns = 0_u64;

    for _ in 0..iterations {
        let check_start = Instant::now();
        let _ = gate.check_trading_allowed(&scope);
        let latency_ns = check_start.elapsed().as_nanos() as u64;

        max_latency_ns = max_latency_ns.max(latency_ns);
        total_latency_ns += latency_ns;
    }

    let total_time = start_time.elapsed();
    let avg_latency_ns = total_latency_ns / iterations;
    let checks_per_second = iterations as f64 / total_time.as_secs_f64();

    info!("\u{1f680} HFT Gate Performance Test Results:");
    info!("   Iterations: {}", iterations);
    info!("   Total time: {:.2}s", total_time.as_secs_f64());
    info!("   Average latency: {}ns", avg_latency_ns);
    info!("   Max latency: {}ns", max_latency_ns);
    info!("   Checks per second: {:.0}", checks_per_second);

    if max_latency_ns <= 1000 {
        info!("   \u{2705} HFT COMPLIANCE: Max latency \u{2264} 1\u{3bc}s");
    } else {
        error!("   \u{274c} HFT NON-COMPLIANCE: Max latency > 1\u{3bc}s");
    }

    Ok(())
}

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

    #[tokio::test]
    async fn test_performance_validation() -> RiskResult<()> {
        let mut tester = KillSwitchPerformanceTester::new().await?;
        let report = tester.validate_regulatory_performance().await?;

        // Basic validation
        assert!(report.gate_check_latency_ns.samples > 0);
        assert!(report.emergency_shutdown_latency_ms.samples > 0);

        // Performance should be reasonable (even in test environment)
        assert!(report.gate_check_latency_ns.avg < 100_000.0); // 100μs max in tests
        assert!(report.emergency_shutdown_latency_ms.avg < 1000.0); // 1s max in tests

        Ok(())
    }

    #[tokio::test]
    async fn test_hft_gate_performance() -> RiskResult<()> {
        run_hft_gate_performance_test(10000).await?;
        Ok(())
    }

    #[tokio::test]
    async fn test_single_gate_check_performance() -> RiskResult<()> {
        let tester = KillSwitchPerformanceTester::new().await?;
        let scope = KillSwitchScope::Symbol("TEST".to_string());

        let start = Instant::now();
        let _ = tester.trading_gate.check_trading_allowed(&scope);
        let latency_ns = start.elapsed().as_nanos();

        // Should be sub-microsecond in most environments
        info!("Single gate check latency: {}ns", latency_ns);
        assert!(latency_ns < 50_000); // 50μs max (generous for test environment)

        Ok(())
    }
}
