//! Regulatory Compliance Tests for Kill Switch System
//!
//! Comprehensive test suite validating regulatory requirements including:
//! - Sub-100ms emergency shutdown compliance
//! - Atomic order blocking capabilities
//! - External control via Unix domain socket
//! - Signal-based emergency response
//! - Audit trail and logging requirements
#![allow(unused_crate_dependencies)]

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

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

use risk::error::RiskResult;
use risk::risk_types::KillSwitchScope;
use risk::safety::kill_switch::AtomicKillSwitch;
use risk::safety::trading_gate::TradingGate;
use risk::safety::unix_socket_kill_switch::{KillSwitchCommand, UnixSocketKillSwitch};
use risk::safety::KillSwitchConfig;

/// Regulatory compliance test suite
pub struct RegulatoryComplianceTests {
    kill_switch: Arc<AtomicKillSwitch>,
    trading_gate: Arc<TradingGate>,
}

impl RegulatoryComplianceTests {
    /// Initialize test suite
    pub async fn new() -> RiskResult<Self> {
        let config = KillSwitchConfig {
            enabled: true,
            global_channel: "compliance_test:global".to_string(),
            strategy_channel_prefix: "compliance_test:strategy".to_string(),
            symbol_channel_prefix: "compliance_test:symbol".to_string(),
            auto_recovery_enabled: false,
            auto_recovery_delay: Duration::from_secs(300),
        };

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

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

        Ok(Self {
            kill_switch,
            trading_gate,
        })
    }

    /// Run all regulatory compliance tests
    pub async fn run_all_compliance_tests(&self) -> RiskResult<ComplianceTestReport> {
        info!("🏛️ STARTING REGULATORY COMPLIANCE TEST SUITE");

        let mut report = ComplianceTestReport {
            emergency_shutdown_compliance: false,
            atomic_blocking_compliance: false,
            external_control_compliance: false,
            signal_response_compliance: false,
            audit_trail_compliance: false,
            performance_compliance: false,
            overall_compliance: false,
        };

        // Test 1: Emergency shutdown response time (<100ms)
        info!("Test 1: Emergency shutdown response time validation");
        report.emergency_shutdown_compliance = self.test_emergency_shutdown_response().await?;

        // Test 2: Atomic order blocking
        info!("Test 2: Atomic order blocking validation");
        report.atomic_blocking_compliance = self.test_atomic_order_blocking().await?;

        // Test 3: External control via Unix socket
        info!("Test 3: External control validation");
        report.external_control_compliance = self.test_external_control().await?;

        // Test 4: Signal-based emergency response
        info!("Test 4: Signal-based emergency response validation");
        report.signal_response_compliance = self.test_signal_based_response().await?;

        // Test 5: Audit trail and logging
        info!("Test 5: Audit trail and logging validation");
        report.audit_trail_compliance = self.test_audit_trail().await?;

        // Test 6: Performance requirements
        info!("Test 6: Performance requirements validation");
        report.performance_compliance = self.test_performance_requirements().await?;

        // Overall compliance assessment
        report.overall_compliance = report.emergency_shutdown_compliance
            && report.atomic_blocking_compliance
            && report.external_control_compliance
            && report.signal_response_compliance
            && report.audit_trail_compliance
            && report.performance_compliance;

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

    /// Test emergency shutdown response time (<100ms requirement)
    async fn test_emergency_shutdown_response(&self) -> RiskResult<bool> {
        info!("🚨 Testing emergency shutdown response time...");

        let mut compliant_shutdowns = 0;
        let total_tests = 50;

        for i in 0..total_tests {
            let scope = KillSwitchScope::Symbol(format!("EMERGENCY_TEST_{}", i));
            let start_time = Instant::now();

            // Activate emergency shutdown
            self.kill_switch
                .engage(
                    scope.clone(),
                    "Emergency compliance test".to_string(),
                    "compliance-test".to_string(),
                    true, // cascade
                )
                .await?;

            let shutdown_time = start_time.elapsed();

            // Verify trading is immediately blocked
            let is_blocked = !self.kill_switch.is_trading_allowed(&scope);

            if shutdown_time.as_millis() <= 100 && is_blocked {
                compliant_shutdowns += 1;
            } else {
                warn!(
                    "Emergency shutdown took {}ms (target: ≤100ms), blocked: {}",
                    shutdown_time.as_millis(),
                    is_blocked
                );
            }

            // Cleanup
            self.kill_switch
                .deactivate(scope, "cleanup".to_string())
                .await?;
        }

        let compliance_rate = (compliant_shutdowns as f64 / total_tests as f64) * 100.0;
        info!(
            "Emergency shutdown compliance: {}/{} ({:.1}%)",
            compliant_shutdowns, total_tests, compliance_rate
        );

        Ok(compliance_rate >= 95.0) // 95% compliance threshold
    }

    /// Test atomic order blocking capabilities
    async fn test_atomic_order_blocking(&self) -> RiskResult<bool> {
        info!("⚡ Testing atomic order blocking...");

        let test_symbols = vec!["AAPL", "GOOGL", "MSFT", "TSLA", "AMZN"];
        let mut successful_blocks = 0;

        for symbol in &test_symbols {
            let scope = KillSwitchScope::Symbol(symbol.to_string());

            // Verify trading is initially allowed
            if !self.trading_gate.check_trading_allowed(&scope).is_ok() {
                warn!("Trading was already blocked for {}", symbol);
                continue;
            }

            // Activate kill switch - now with correct 4-argument signature
            self.kill_switch
                .activate(
                    scope.clone(),
                    "Atomic blocking test".to_string(),
                    "compliance-test".to_string(),
                    false, // cascade
                )
                .await?;

            // Verify immediate blocking
            let is_immediately_blocked = self.trading_gate.check_trading_allowed(&scope).is_err();

            if is_immediately_blocked {
                successful_blocks += 1;
                info!(
                    "✅ {} immediately blocked after kill switch activation",
                    symbol
                );
            } else {
                warn!("❌ {} not immediately blocked", symbol);
            }

            // Cleanup
            self.kill_switch
                .deactivate(scope, "cleanup".to_string())
                .await?;
        }

        let success_rate = (successful_blocks as f64 / test_symbols.len() as f64) * 100.0;
        info!(
            "Atomic blocking success rate: {}/{} ({:.1}%)",
            successful_blocks,
            test_symbols.len(),
            success_rate
        );

        Ok(success_rate == 100.0) // Must be 100% for regulatory compliance
    }

    /// Test external control via Unix domain socket
    async fn test_external_control(&self) -> RiskResult<bool> {
        info!("🔌 Testing external control via Unix socket...");

        // Create temporary Unix socket for testing
        let socket_path = "/tmp/compliance_test_kill_switch.sock".to_string();
        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 successful_commands = 0;
        let total_commands = 10;

        // Use a test auth token
        let test_auth_token = "test-compliance-token".to_string();

        for i in 0..total_commands {
            let test_scope = KillSwitchScope::Symbol(format!("EXTERNAL_TEST_{}", i));

            // Test activation via Unix socket - now with auth_token field
            let activate_result = timeout(
                Duration::from_millis(100),
                UnixSocketKillSwitch::send_command_to_socket(
                    &socket_path,
                    KillSwitchCommand::Activate {
                        scope: test_scope.clone(),
                        reason: "External control test".to_string(),
                        cascade: false,
                        auth_token: test_auth_token.clone(),
                    },
                ),
            )
            .await;

            match activate_result {
                Ok(Ok(response)) if response.success => {
                    // Verify kill switch is active
                    if !self.kill_switch.is_trading_allowed(&test_scope) {
                        successful_commands += 1;
                        info!("✅ External activation successful for test {}", i);

                        // Deactivate via Unix socket - now with auth_token field
                        let _ = UnixSocketKillSwitch::send_command_to_socket(
                            &socket_path,
                            KillSwitchCommand::Deactivate {
                                scope: test_scope,
                                auth_token: test_auth_token.clone(),
                            },
                        )
                        .await;
                    } else {
                        warn!("❌ External activation claimed success but kill switch not active");
                    }
                },
                Ok(Ok(response)) => {
                    warn!("❌ External command failed: {}", response.message);
                },
                Ok(Err(e)) => {
                    warn!("❌ External command error: {}", e);
                },
                Err(_) => {
                    warn!("❌ External command timed out");
                },
            }
        }

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

        let success_rate = (successful_commands as f64 / total_commands as f64) * 100.0;
        info!(
            "External control success rate: {}/{} ({:.1}%)",
            successful_commands, total_commands, success_rate
        );

        Ok(success_rate >= 90.0) // 90% threshold (allowing for test environment issues)
    }

    /// Test signal-based emergency response
    async fn test_signal_based_response(&self) -> RiskResult<bool> {
        info!("📡 Testing signal-based emergency response...");

        // Test direct signal-style engagement (simulating SIGUSR1/SIGUSR2)
        let mut successful_responses = 0;
        let total_tests = 5;

        for i in 0..total_tests {
            let test_scope = KillSwitchScope::Symbol(format!("SIGNAL_TEST_{}", i));
            let start_time = Instant::now();

            // Simulate signal-based emergency engagement
            self.kill_switch
                .engage(
                    test_scope.clone(),
                    "Signal-based emergency test".to_string(),
                    "signal-handler".to_string(),
                    true, // cascade for signal-based shutdowns
                )
                .await?;

            let response_time = start_time.elapsed();

            // Verify immediate blocking and fast response
            let is_blocked = !self.kill_switch.is_trading_allowed(&test_scope);
            let response_compliant = response_time.as_millis() <= 10; // <10ms for signal response

            if is_blocked && response_compliant {
                successful_responses += 1;
                info!(
                    "✅ Signal response test {} successful ({}ms)",
                    i,
                    response_time.as_millis()
                );
            } else {
                warn!(
                    "❌ Signal response test {} failed - blocked: {}, time: {}ms",
                    i,
                    is_blocked,
                    response_time.as_millis()
                );
            }

            // Cleanup
            self.kill_switch
                .deactivate(test_scope, "cleanup".to_string())
                .await?;
        }

        let success_rate = (successful_responses as f64 / total_tests as f64) * 100.0;
        info!(
            "Signal response success rate: {}/{} ({:.1}%)",
            successful_responses, total_tests, success_rate
        );

        Ok(success_rate >= 80.0) // 80% threshold (signal handling can be environment-dependent)
    }

    /// Test audit trail and logging requirements
    async fn test_audit_trail(&self) -> RiskResult<bool> {
        info!("📋 Testing audit trail and logging...");

        // Test various operations to ensure audit logging
        let test_scope = KillSwitchScope::Symbol("AUDIT_TEST".to_string());

        // Activation with audit - now with correct 4-argument signature
        self.kill_switch
            .activate(
                test_scope.clone(),
                "Audit trail test".to_string(),
                "audit-test-user".to_string(),
                false, // cascade
            )
            .await?;

        // Multiple checks (should be logged)
        for _ in 0..10 {
            let _ = self.kill_switch.is_trading_allowed(&test_scope);
        }

        // Deactivation with audit
        self.kill_switch
            .deactivate(test_scope, "audit-test".to_string())
            .await?;

        // Get metrics to verify logging occurred
        let (total_checks, total_commands) = self.kill_switch.get_metrics();

        info!(
            "Audit metrics - Checks: {}, Commands: {}",
            total_checks, total_commands
        );

        // Verify that operations were recorded
        let audit_compliant = total_checks >= 10 && total_commands >= 2;

        if audit_compliant {
            info!("✅ Audit trail compliance verified");
        } else {
            warn!("❌ Audit trail compliance failed");
        }

        Ok(audit_compliant)
    }

    /// Test performance requirements
    async fn test_performance_requirements(&self) -> RiskResult<bool> {
        info!("🚀 Testing performance requirements...");

        // Run basic performance checks
        let start = Instant::now();
        let test_scope = KillSwitchScope::Symbol("PERF_TEST".to_string());
        let _allowed = self.trading_gate.check_trading_allowed(&test_scope);
        let gate_check_latency = start.elapsed();

        let gate_compliant = gate_check_latency < Duration::from_micros(100); // Sub-100μs requirement

        info!(
            "Performance compliance - Gate: {} ({}μs)",
            if gate_compliant { "✅" } else { "❌" },
            gate_check_latency.as_micros()
        );

        let overall_performance_compliant = gate_compliant;

        if overall_performance_compliant {
            info!("✅ All performance requirements met");
        } else {
            warn!("❌ Performance requirements not fully met");
        }

        Ok(overall_performance_compliant)
    }

    /// Log comprehensive compliance report
    async fn log_compliance_report(&self, report: &ComplianceTestReport) {
        info!("📊 REGULATORY COMPLIANCE TEST REPORT");
        info!("=====================================");

        info!(
            "🚨 Emergency Shutdown: {}",
            if report.emergency_shutdown_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "⚡ Atomic Order Blocking: {}",
            if report.atomic_blocking_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "🔌 External Control: {}",
            if report.external_control_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "📡 Signal Response: {}",
            if report.signal_response_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "📋 Audit Trail: {}",
            if report.audit_trail_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "🚀 Performance: {}",
            if report.performance_compliance {
                "✅ COMPLIANT"
            } else {
                "❌ NON-COMPLIANT"
            }
        );

        info!(
            "🏛️ OVERALL COMPLIANCE: {}",
            if report.overall_compliance {
                "✅ FULLY COMPLIANT - Ready for regulatory deployment"
            } else {
                "❌ NON-COMPLIANT - Regulatory requirements not met"
            }
        );
    }
}

/// Compliance test report
#[derive(Debug, Clone)]
pub struct ComplianceTestReport {
    pub emergency_shutdown_compliance: bool,
    pub atomic_blocking_compliance: bool,
    pub external_control_compliance: bool,
    pub signal_response_compliance: bool,
    pub audit_trail_compliance: bool,
    pub performance_compliance: bool,
    pub overall_compliance: bool,
}

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

    #[tokio::test]
    async fn test_regulatory_compliance_suite() -> RiskResult<()> {
        // Initialize logging for test visibility
        tracing_subscriber::fmt()
            .with_env_filter("info")
            .try_init()
            .ok();

        let compliance_tests = RegulatoryComplianceTests::new().await?;
        let report = compliance_tests.run_all_compliance_tests().await?;

        // In a real regulatory environment, this should be true
        // In test environment, we'll check individual components
        info!(
            "Compliance test completed. Overall compliant: {}",
            report.overall_compliance
        );

        // These should always pass regardless of environment
        assert!(
            report.atomic_blocking_compliance,
            "Atomic blocking must be compliant"
        );
        assert!(
            report.audit_trail_compliance,
            "Audit trail must be compliant"
        );

        Ok(())
    }

    #[tokio::test]
    async fn test_emergency_shutdown_only() -> RiskResult<()> {
        let compliance_tests = RegulatoryComplianceTests::new().await?;
        let result = compliance_tests.test_emergency_shutdown_response().await?;

        info!("Emergency shutdown compliance: {}", result);

        // Should meet performance requirements in most environments
        assert!(result, "Emergency shutdown response time compliance failed");

        Ok(())
    }

    #[tokio::test]
    async fn test_atomic_blocking_only() -> RiskResult<()> {
        let compliance_tests = RegulatoryComplianceTests::new().await?;
        let result = compliance_tests.test_atomic_order_blocking().await?;

        info!("Atomic blocking compliance: {}", result);

        // This should always pass
        assert!(result, "Atomic blocking compliance failed");

        Ok(())
    }
}
