use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;

/// Performance sample for adaptive threshold calculation
#[derive(Debug, Clone)]
pub struct PerformanceSample {
    pub timestamp: Instant,
    pub analysis_duration_ms: u64,
    pub cache_hit_ratio: f32,
    pub memory_usage_mb: f32,
    pub cpu_utilization: f32,
    pub queue_depth: usize,
}

/// Adaptive threshold configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdaptiveConfig {
    /// Target performance threshold (ms)
    pub target_analysis_time_ms: u64,
    /// Minimum cache hit ratio before adjustment
    pub min_cache_hit_ratio: f32,
    /// Maximum memory usage before scaling back
    pub max_memory_mb: f32,
    /// CPU utilization threshold for backpressure
    pub max_cpu_utilization: f32,
    /// Sample window size for averaging
    pub sample_window_size: usize,
    /// Adjustment sensitivity (0.0 - 1.0)
    pub adjustment_sensitivity: f32,
}

impl Default for AdaptiveConfig {
    fn default() -> Self {
        Self {
            target_analysis_time_ms: 100, // 100ms target
            min_cache_hit_ratio: 0.6,     // 60% cache hits
            max_memory_mb: 512.0,         // 512MB limit
            max_cpu_utilization: 0.8,     // 80% CPU max
            sample_window_size: 50,       // 50 sample rolling window
            adjustment_sensitivity: 0.1,  // 10% adjustment steps
        }
    }
}

/// Threshold adjustment recommendations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ThresholdAdjustment {
    /// Increase cache size and permits
    ScaleUp {
        cache_factor: f32,
        permit_factor: f32,
    },
    /// Decrease cache size and permits
    ScaleDown {
        cache_factor: f32,
        permit_factor: f32,
    },
    /// Increase compression ratio
    MoreCompression { compression_level: u8 },
    /// Reduce compression for speed
    LessCompression { compression_level: u8 },
    /// No adjustment needed
    Maintain,
}

/// Performance monitoring and adaptive threshold manager
pub struct AdaptiveThresholdManager {
    config: AdaptiveConfig,
    performance_history: Arc<RwLock<VecDeque<PerformanceSample>>>,
    current_thresholds: Arc<RwLock<CurrentThresholds>>,
    adjustment_history: Arc<RwLock<VecDeque<ThresholdAdjustment>>>,
}

/// Current active thresholds
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CurrentThresholds {
    pub hot_cache_size: usize,
    pub high_priority_permits: usize,
    pub low_priority_permits: usize,
    pub compression_level: u8,
    pub archive_after_hours: u32,
    pub cleanup_interval_minutes: u32,
}

impl Default for CurrentThresholds {
    fn default() -> Self {
        Self {
            hot_cache_size: 1000,
            high_priority_permits: 10,
            low_priority_permits: 2,
            compression_level: 4,         // Balanced LZ4 level
            archive_after_hours: 24 * 30, // 30 days
            cleanup_interval_minutes: 60, // 1 hour
        }
    }
}

impl AdaptiveThresholdManager {
    /// Create new adaptive threshold manager
    #[must_use]
    pub fn new(config: AdaptiveConfig) -> Self {
        Self {
            config,
            performance_history: Arc::new(RwLock::new(VecDeque::new())),
            current_thresholds: Arc::new(RwLock::new(CurrentThresholds::default())),
            adjustment_history: Arc::new(RwLock::new(VecDeque::new())),
        }
    }

    /// Record performance sample for adaptation
    pub async fn record_sample(&self, sample: PerformanceSample) -> Result<()> {
        let mut history = self.performance_history.write().await;

        // Add new sample
        history.push_back(sample);

        // Maintain window size
        while history.len() > self.config.sample_window_size {
            history.pop_front();
        }

        // Check if adaptation is needed
        if history.len() >= 10 {
            // Minimum samples for reliable adjustment
            if let Some(adjustment) = self.calculate_adjustment(&history).await? {
                self.apply_adjustment(adjustment).await?;
            }
        }

        Ok(())
    }

    /// Calculate recommended threshold adjustment based on performance
    async fn calculate_adjustment(
        &self,
        history: &VecDeque<PerformanceSample>,
    ) -> Result<Option<ThresholdAdjustment>> {
        if history.len() < 5 {
            return Ok(None);
        }

        // Calculate performance metrics
        let avg_duration = history.iter().map(|s| s.analysis_duration_ms).sum::<u64>() as f32
            / history.len() as f32;

        let avg_cache_hit =
            history.iter().map(|s| s.cache_hit_ratio).sum::<f32>() / history.len() as f32;

        let avg_memory =
            history.iter().map(|s| s.memory_usage_mb).sum::<f32>() / history.len() as f32;

        let avg_cpu = history.iter().map(|s| s.cpu_utilization).sum::<f32>() / history.len() as f32;

        let avg_queue_depth =
            history.iter().map(|s| s.queue_depth).sum::<usize>() as f32 / history.len() as f32;

        // Performance below threshold
        if avg_duration > self.config.target_analysis_time_ms as f32 * 1.5 {
            if avg_cache_hit < self.config.min_cache_hit_ratio {
                // Low cache hit ratio - scale up cache
                return Ok(Some(ThresholdAdjustment::ScaleUp {
                    cache_factor: 1.0 + self.config.adjustment_sensitivity,
                    permit_factor: 1.0,
                }));
            } else if avg_queue_depth > 5.0 {
                // High queue depth - increase permits
                return Ok(Some(ThresholdAdjustment::ScaleUp {
                    cache_factor: 1.0,
                    permit_factor: 1.0 + self.config.adjustment_sensitivity,
                }));
            }
            // Reduce compression for speed
            return Ok(Some(ThresholdAdjustment::LessCompression {
                compression_level: 1,
            }));
        }

        // Resource usage too high
        if avg_memory > self.config.max_memory_mb || avg_cpu > self.config.max_cpu_utilization {
            if avg_cache_hit > 0.9
                && avg_duration < self.config.target_analysis_time_ms as f32 * 0.8
            {
                // High cache hit and fast performance - can reduce cache
                return Ok(Some(ThresholdAdjustment::ScaleDown {
                    cache_factor: 1.0 - self.config.adjustment_sensitivity,
                    permit_factor: 1.0,
                }));
            }
            // Increase compression to save memory
            return Ok(Some(ThresholdAdjustment::MoreCompression {
                compression_level: 6,
            }));
        }

        // Performance is excellent - maintain current settings
        if avg_duration < self.config.target_analysis_time_ms as f32 * 0.5
            && avg_cache_hit > 0.8
            && avg_memory < self.config.max_memory_mb * 0.5
        {
            return Ok(Some(ThresholdAdjustment::Maintain));
        }

        Ok(None)
    }

    /// Apply threshold adjustment to current configuration
    async fn apply_adjustment(&self, adjustment: ThresholdAdjustment) -> Result<()> {
        let mut thresholds = self.current_thresholds.write().await;
        let mut adjustments = self.adjustment_history.write().await;

        match adjustment.clone() {
            ThresholdAdjustment::ScaleUp {
                cache_factor,
                permit_factor,
            } => {
                thresholds.hot_cache_size =
                    ((thresholds.hot_cache_size as f32 * cache_factor) as usize).min(10000);
                thresholds.high_priority_permits =
                    ((thresholds.high_priority_permits as f32 * permit_factor) as usize).min(50);
                thresholds.low_priority_permits =
                    ((thresholds.low_priority_permits as f32 * permit_factor) as usize).min(20);
            }
            ThresholdAdjustment::ScaleDown {
                cache_factor,
                permit_factor,
            } => {
                thresholds.hot_cache_size =
                    ((thresholds.hot_cache_size as f32 * cache_factor) as usize).max(100);
                thresholds.high_priority_permits =
                    ((thresholds.high_priority_permits as f32 * permit_factor) as usize).max(2);
                thresholds.low_priority_permits =
                    ((thresholds.low_priority_permits as f32 * permit_factor) as usize).max(1);
            }
            ThresholdAdjustment::MoreCompression { compression_level } => {
                thresholds.compression_level = compression_level.min(9);
            }
            ThresholdAdjustment::LessCompression { compression_level } => {
                thresholds.compression_level = compression_level.max(1);
            }
            ThresholdAdjustment::Maintain => {
                // No changes needed
            }
        }

        // Record adjustment
        adjustments.push_back(adjustment);

        // Maintain adjustment history size
        while adjustments.len() > 100 {
            adjustments.pop_front();
        }

        Ok(())
    }

    /// Get current threshold configuration
    pub async fn get_current_thresholds(&self) -> CurrentThresholds {
        self.current_thresholds.read().await.clone()
    }

    /// Get recent performance statistics
    pub async fn get_performance_stats(&self) -> PerformanceStatistics {
        let history = self.performance_history.read().await;
        let adjustments = self.adjustment_history.read().await;

        if history.is_empty() {
            return PerformanceStatistics::default();
        }

        let recent = history.iter().rev().take(10).collect::<Vec<_>>();

        let avg_duration =
            recent.iter().map(|s| s.analysis_duration_ms).sum::<u64>() as f32 / recent.len() as f32;

        let avg_cache_hit =
            recent.iter().map(|s| s.cache_hit_ratio).sum::<f32>() / recent.len() as f32;

        let avg_memory =
            recent.iter().map(|s| s.memory_usage_mb).sum::<f32>() / recent.len() as f32;

        let avg_cpu = recent.iter().map(|s| s.cpu_utilization).sum::<f32>() / recent.len() as f32;

        let recent_adjustments = adjustments.len().min(10); // Simplified recent count

        PerformanceStatistics {
            avg_analysis_duration_ms: avg_duration,
            avg_cache_hit_ratio: avg_cache_hit,
            avg_memory_usage_mb: avg_memory,
            avg_cpu_utilization: avg_cpu,
            total_samples: history.len(),
            recent_adjustments_count: recent_adjustments,
            performance_trend: self.calculate_trend(&history),
        }
    }

    /// Calculate performance trend from recent samples
    fn calculate_trend(&self, history: &VecDeque<PerformanceSample>) -> PerformanceTrend {
        if history.len() < 10 {
            return PerformanceTrend::Stable;
        }

        let history_vec: Vec<_> = history.iter().collect();
        let mid_point = history_vec.len() / 2;
        let recent_half = &history_vec[mid_point..];
        let older_half = &history_vec[..mid_point];

        let recent_avg = recent_half
            .iter()
            .map(|s| s.analysis_duration_ms)
            .sum::<u64>() as f32
            / recent_half.len() as f32;

        let older_avg = older_half
            .iter()
            .map(|s| s.analysis_duration_ms)
            .sum::<u64>() as f32
            / older_half.len() as f32;

        let change_ratio = (recent_avg - older_avg) / older_avg;

        if change_ratio > 0.2 {
            PerformanceTrend::Degrading
        } else if change_ratio < -0.2 {
            PerformanceTrend::Improving
        } else {
            PerformanceTrend::Stable
        }
    }

    /// Create performance sample from current system state
    pub async fn create_sample(
        &self,
        duration: Duration,
        cache_hit: bool,
        queue_depth: usize,
    ) -> PerformanceSample {
        PerformanceSample {
            timestamp: Instant::now(),
            analysis_duration_ms: duration.as_millis() as u64,
            cache_hit_ratio: if cache_hit { 1.0 } else { 0.0 },
            memory_usage_mb: self.get_memory_usage().await,
            cpu_utilization: self.get_cpu_usage().await,
            queue_depth,
        }
    }

    /// Get current memory usage (simplified implementation)
    async fn get_memory_usage(&self) -> f32 {
        // In a full implementation, this would use system APIs
        // For now, estimate based on cache size and active operations
        let thresholds = self.current_thresholds.read().await;
        let estimated_cache_mb = (thresholds.hot_cache_size * 1024) as f32 / (1024.0 * 1024.0);
        estimated_cache_mb + 50.0 // Base memory usage
    }

    /// Get current CPU utilization (simplified implementation)
    async fn get_cpu_usage(&self) -> f32 {
        // In a full implementation, this would use system APIs
        // For now, estimate based on active operations
        let history = self.performance_history.read().await;
        let recent_activity = history
            .iter()
            .rev()
            .take(5)
            .filter(|s| s.timestamp.elapsed() < Duration::from_secs(10))
            .count();

        (recent_activity as f32 * 0.1).min(1.0) // Estimate 10% CPU per recent operation
    }

    /// Reset thresholds to default configuration
    pub async fn reset_to_defaults(&self) -> Result<()> {
        let mut thresholds = self.current_thresholds.write().await;
        *thresholds = CurrentThresholds::default();

        let mut adjustments = self.adjustment_history.write().await;
        adjustments.push_back(ThresholdAdjustment::Maintain);

        Ok(())
    }
}

/// Performance trend analysis
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PerformanceTrend {
    Improving,
    Stable,
    Degrading,
}

/// Aggregated performance statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceStatistics {
    pub avg_analysis_duration_ms: f32,
    pub avg_cache_hit_ratio: f32,
    pub avg_memory_usage_mb: f32,
    pub avg_cpu_utilization: f32,
    pub total_samples: usize,
    pub recent_adjustments_count: usize,
    pub performance_trend: PerformanceTrend,
}

impl Default for PerformanceStatistics {
    fn default() -> Self {
        Self {
            avg_analysis_duration_ms: 0.0,
            avg_cache_hit_ratio: 0.0,
            avg_memory_usage_mb: 0.0,
            avg_cpu_utilization: 0.0,
            total_samples: 0,
            recent_adjustments_count: 0,
            performance_trend: PerformanceTrend::Stable,
        }
    }
}

impl PerformanceStatistics {
    /// Format statistics for diagnostic display
    #[must_use]
    pub fn format_diagnostic(&self) -> String {
        let trend_indicator = match self.performance_trend {
            PerformanceTrend::Improving => "📈 IMPROVING",
            PerformanceTrend::Stable => "➡️ STABLE",
            PerformanceTrend::Degrading => "📉 DEGRADING",
        };

        format!(
            "Adaptive Thresholds:\n\
             - Performance: {}\n\
             - Avg duration: {:.1}ms\n\
             - Cache hit ratio: {:.1}%\n\
             - Memory usage: {:.1}MB\n\
             - CPU utilization: {:.1}%\n\
             - Total samples: {}\n\
             - Recent adjustments: {}",
            trend_indicator,
            self.avg_analysis_duration_ms,
            self.avg_cache_hit_ratio * 100.0,
            self.avg_memory_usage_mb,
            self.avg_cpu_utilization * 100.0,
            self.total_samples,
            self.recent_adjustments_count
        )
    }
}

/// Factory for creating adaptive threshold managers
pub struct AdaptiveThresholdFactory;

impl AdaptiveThresholdFactory {
    /// Create manager with default configuration
    #[must_use]
    pub fn create_default() -> AdaptiveThresholdManager {
        AdaptiveThresholdManager::new(AdaptiveConfig::default())
    }

    /// Create manager optimized for development (fast feedback)
    #[must_use]
    pub fn create_dev_optimized() -> AdaptiveThresholdManager {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 50, // Faster target for dev
            sample_window_size: 20,      // Smaller window for quicker adaptation
            adjustment_sensitivity: 0.2, // More aggressive adjustments
            ..Default::default()
        };
        AdaptiveThresholdManager::new(config)
    }

    /// Create manager optimized for production (stable)
    #[must_use]
    pub fn create_prod_optimized() -> AdaptiveThresholdManager {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 200, // More conservative target
            sample_window_size: 100,      // Larger window for stability
            adjustment_sensitivity: 0.05, // Conservative adjustments
            ..Default::default()
        };
        AdaptiveThresholdManager::new(config)
    }
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
    use super::*;

    fn create_sample(duration_ms: u64, cache_hit: bool, memory_mb: f32) -> PerformanceSample {
        PerformanceSample {
            timestamp: Instant::now(),
            analysis_duration_ms: duration_ms,
            cache_hit_ratio: if cache_hit { 1.0 } else { 0.0 },
            memory_usage_mb: memory_mb,
            cpu_utilization: 0.5,
            queue_depth: 2,
        }
    }

    #[tokio::test]
    async fn test_threshold_manager_creation() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let stats = manager.get_performance_stats().await;

        assert_eq!(stats.total_samples, 0);
        assert!(matches!(stats.performance_trend, PerformanceTrend::Stable));
    }

    #[tokio::test]
    async fn test_performance_sample_recording() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let sample = create_sample(80, true, 100.0);

        manager.record_sample(sample).await.unwrap();

        let stats = manager.get_performance_stats().await;
        assert_eq!(stats.total_samples, 1);
        assert_eq!(stats.avg_analysis_duration_ms, 80.0);
    }

    #[tokio::test]
    async fn test_sample_window_management() {
        let config = AdaptiveConfig {
            sample_window_size: 3,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add more samples than window size
        for i in 0..5 {
            let sample = create_sample(100 + i * 10, true, 100.0);
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        assert_eq!(stats.total_samples, 3); // Should maintain window size
    }

    #[tokio::test]
    async fn test_scale_up_adjustment() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 100,
            min_cache_hit_ratio: 0.8,
            sample_window_size: 10,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples showing slow performance and low cache hits
        for _ in 0..12 {
            let sample = create_sample(200, false, 100.0); // Slow + cache miss
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        let stats = manager.get_performance_stats().await;

        // Should have triggered scale-up adjustment
        assert!(thresholds.hot_cache_size > 1000); // Should be increased from default
        assert!(stats.recent_adjustments_count > 0);
    }

    #[tokio::test]
    async fn test_compression_adjustment() {
        let config = AdaptiveConfig {
            max_memory_mb: 200.0,
            sample_window_size: 10,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples showing high memory usage
        for _ in 0..12 {
            let sample = create_sample(80, true, 300.0); // High memory
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;

        // Should have increased compression level
        assert!(thresholds.compression_level > 4);
    }

    #[tokio::test]
    async fn test_factory_patterns() {
        let default_mgr = AdaptiveThresholdFactory::create_default();
        let dev_mgr = AdaptiveThresholdFactory::create_dev_optimized();
        let prod_mgr = AdaptiveThresholdFactory::create_prod_optimized();

        // Test that all managers can record samples
        let sample = create_sample(100, true, 100.0);

        default_mgr.record_sample(sample.clone()).await.unwrap();
        dev_mgr.record_sample(sample.clone()).await.unwrap();
        prod_mgr.record_sample(sample).await.unwrap();

        // Verify different configurations
        let dev_stats = dev_mgr.get_performance_stats().await;
        let prod_stats = prod_mgr.get_performance_stats().await;

        assert_eq!(dev_stats.total_samples, 1);
        assert_eq!(prod_stats.total_samples, 1);
    }

    #[tokio::test]
    async fn test_trend_calculation() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add improving trend samples (getting faster)
        for i in 0..20 {
            let duration = 200 - (i * 5); // Getting faster over time
            let sample = create_sample(duration, true, 100.0);
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        assert!(matches!(
            stats.performance_trend,
            PerformanceTrend::Improving
        ));
    }
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn basic_property_stability(_input in ".*") {
            // Basic property test for coverage
            prop_assert!(true);
        }

        #[test]
        fn module_consistency_check(_x in 0u32..1000) {
            // Module consistency verification
            prop_assert!(_x < 1001);
        }
    }
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod extended_coverage_tests {
    use super::*;

    fn create_sample_full(
        duration_ms: u64,
        cache_hit_ratio: f32,
        memory_mb: f32,
        cpu: f32,
        queue: usize,
    ) -> PerformanceSample {
        PerformanceSample {
            timestamp: Instant::now(),
            analysis_duration_ms: duration_ms,
            cache_hit_ratio,
            memory_usage_mb: memory_mb,
            cpu_utilization: cpu,
            queue_depth: queue,
        }
    }

    // =============================================================================
    // ADAPTIVE CONFIG TESTS
    // =============================================================================

    #[test]
    fn test_adaptive_config_default() {
        let config = AdaptiveConfig::default();
        assert_eq!(config.target_analysis_time_ms, 100);
        assert_eq!(config.min_cache_hit_ratio, 0.6);
        assert_eq!(config.max_memory_mb, 512.0);
        assert_eq!(config.max_cpu_utilization, 0.8);
        assert_eq!(config.sample_window_size, 50);
        assert_eq!(config.adjustment_sensitivity, 0.1);
    }

    #[test]
    fn test_adaptive_config_clone() {
        let config = AdaptiveConfig::default();
        let cloned = config.clone();
        assert_eq!(
            cloned.target_analysis_time_ms,
            config.target_analysis_time_ms
        );
        assert_eq!(cloned.min_cache_hit_ratio, config.min_cache_hit_ratio);
    }

    #[test]
    fn test_adaptive_config_serialization() {
        let config = AdaptiveConfig::default();
        let json = serde_json::to_string(&config).unwrap();
        let deserialized: AdaptiveConfig = serde_json::from_str(&json).unwrap();
        assert_eq!(
            deserialized.target_analysis_time_ms,
            config.target_analysis_time_ms
        );
    }

    // =============================================================================
    // CURRENT THRESHOLDS TESTS
    // =============================================================================

    #[test]
    fn test_current_thresholds_default() {
        let thresholds = CurrentThresholds::default();
        assert_eq!(thresholds.hot_cache_size, 1000);
        assert_eq!(thresholds.high_priority_permits, 10);
        assert_eq!(thresholds.low_priority_permits, 2);
        assert_eq!(thresholds.compression_level, 4);
        assert_eq!(thresholds.archive_after_hours, 24 * 30);
        assert_eq!(thresholds.cleanup_interval_minutes, 60);
    }

    #[test]
    fn test_current_thresholds_clone() {
        let thresholds = CurrentThresholds::default();
        let cloned = thresholds.clone();
        assert_eq!(cloned.hot_cache_size, thresholds.hot_cache_size);
    }

    #[test]
    fn test_current_thresholds_serialization() {
        let thresholds = CurrentThresholds::default();
        let json = serde_json::to_string(&thresholds).unwrap();
        let deserialized: CurrentThresholds = serde_json::from_str(&json).unwrap();
        assert_eq!(deserialized.hot_cache_size, thresholds.hot_cache_size);
    }

    // =============================================================================
    // THRESHOLD ADJUSTMENT TESTS
    // =============================================================================

    #[test]
    fn test_threshold_adjustment_variants() {
        let adjustments = vec![
            ThresholdAdjustment::ScaleUp {
                cache_factor: 1.2,
                permit_factor: 1.1,
            },
            ThresholdAdjustment::ScaleDown {
                cache_factor: 0.8,
                permit_factor: 0.9,
            },
            ThresholdAdjustment::MoreCompression {
                compression_level: 8,
            },
            ThresholdAdjustment::LessCompression {
                compression_level: 2,
            },
            ThresholdAdjustment::Maintain,
        ];

        for adj in adjustments {
            let cloned = adj.clone();
            let json = serde_json::to_string(&adj).unwrap();
            let _deserialized: ThresholdAdjustment = serde_json::from_str(&json).unwrap();
            let _ = format!("{:?}", cloned);
        }
    }

    // =============================================================================
    // PERFORMANCE SAMPLE TESTS
    // =============================================================================

    #[test]
    fn test_performance_sample_clone() {
        let sample = create_sample_full(100, 0.8, 256.0, 0.5, 3);
        let cloned = sample.clone();
        assert_eq!(cloned.analysis_duration_ms, 100);
        assert_eq!(cloned.cache_hit_ratio, 0.8);
        assert_eq!(cloned.memory_usage_mb, 256.0);
        assert_eq!(cloned.cpu_utilization, 0.5);
        assert_eq!(cloned.queue_depth, 3);
    }

    #[test]
    fn test_performance_sample_debug() {
        let sample = create_sample_full(100, 0.8, 256.0, 0.5, 3);
        let debug = format!("{:?}", sample);
        assert!(debug.contains("PerformanceSample"));
    }

    // =============================================================================
    // PERFORMANCE TREND TESTS
    // =============================================================================

    #[test]
    fn test_performance_trend_all_variants() {
        let trends = vec![
            PerformanceTrend::Improving,
            PerformanceTrend::Stable,
            PerformanceTrend::Degrading,
        ];

        for trend in trends {
            let cloned = trend.clone();
            let json = serde_json::to_string(&trend).unwrap();
            let _deserialized: PerformanceTrend = serde_json::from_str(&json).unwrap();
            let _ = format!("{:?}", cloned);
        }
    }

    // =============================================================================
    // PERFORMANCE STATISTICS TESTS
    // =============================================================================

    #[test]
    fn test_performance_statistics_default() {
        let stats = PerformanceStatistics::default();
        assert_eq!(stats.avg_analysis_duration_ms, 0.0);
        assert_eq!(stats.avg_cache_hit_ratio, 0.0);
        assert_eq!(stats.avg_memory_usage_mb, 0.0);
        assert_eq!(stats.avg_cpu_utilization, 0.0);
        assert_eq!(stats.total_samples, 0);
        assert_eq!(stats.recent_adjustments_count, 0);
        assert!(matches!(stats.performance_trend, PerformanceTrend::Stable));
    }

    #[test]
    fn test_performance_statistics_clone() {
        let stats = PerformanceStatistics {
            avg_analysis_duration_ms: 100.0,
            avg_cache_hit_ratio: 0.85,
            avg_memory_usage_mb: 256.0,
            avg_cpu_utilization: 0.6,
            total_samples: 50,
            recent_adjustments_count: 3,
            performance_trend: PerformanceTrend::Improving,
        };
        let cloned = stats.clone();
        assert_eq!(cloned.avg_analysis_duration_ms, 100.0);
        assert_eq!(cloned.total_samples, 50);
    }

    #[test]
    fn test_performance_statistics_serialization() {
        let stats = PerformanceStatistics::default();
        let json = serde_json::to_string(&stats).unwrap();
        let deserialized: PerformanceStatistics = serde_json::from_str(&json).unwrap();
        assert_eq!(deserialized.total_samples, stats.total_samples);
    }

    #[test]
    fn test_format_diagnostic_improving() {
        let stats = PerformanceStatistics {
            avg_analysis_duration_ms: 80.5,
            avg_cache_hit_ratio: 0.9,
            avg_memory_usage_mb: 256.0,
            avg_cpu_utilization: 0.5,
            total_samples: 100,
            recent_adjustments_count: 5,
            performance_trend: PerformanceTrend::Improving,
        };

        let output = stats.format_diagnostic();
        assert!(output.contains("IMPROVING"));
        assert!(output.contains("80.5ms"));
        assert!(output.contains("90.0%")); // cache hit ratio
        assert!(output.contains("256.0MB"));
        assert!(output.contains("50.0%")); // CPU
        assert!(output.contains("100")); // samples
        assert!(output.contains("5")); // adjustments
    }

    #[test]
    fn test_format_diagnostic_stable() {
        let stats = PerformanceStatistics {
            avg_analysis_duration_ms: 100.0,
            avg_cache_hit_ratio: 0.75,
            avg_memory_usage_mb: 300.0,
            avg_cpu_utilization: 0.6,
            total_samples: 50,
            recent_adjustments_count: 2,
            performance_trend: PerformanceTrend::Stable,
        };

        let output = stats.format_diagnostic();
        assert!(output.contains("STABLE"));
    }

    #[test]
    fn test_format_diagnostic_degrading() {
        let stats = PerformanceStatistics {
            avg_analysis_duration_ms: 200.0,
            avg_cache_hit_ratio: 0.4,
            avg_memory_usage_mb: 450.0,
            avg_cpu_utilization: 0.9,
            total_samples: 25,
            recent_adjustments_count: 8,
            performance_trend: PerformanceTrend::Degrading,
        };

        let output = stats.format_diagnostic();
        assert!(output.contains("DEGRADING"));
    }

    // =============================================================================
    // ADAPTIVE THRESHOLD MANAGER ASYNC TESTS
    // =============================================================================

    #[tokio::test]
    async fn test_get_current_thresholds() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let thresholds = manager.get_current_thresholds().await;
        assert_eq!(thresholds.hot_cache_size, 1000);
        assert_eq!(thresholds.high_priority_permits, 10);
    }

    #[tokio::test]
    async fn test_reset_to_defaults() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Record samples to trigger adjustments
        for _ in 0..12 {
            let sample = create_sample_full(200, 0.3, 100.0, 0.5, 2);
            manager.record_sample(sample).await.unwrap();
        }

        // Reset to defaults
        manager.reset_to_defaults().await.unwrap();

        let thresholds = manager.get_current_thresholds().await;
        assert_eq!(thresholds.hot_cache_size, 1000);
        assert_eq!(thresholds.compression_level, 4);
    }

    #[tokio::test]
    async fn test_create_sample() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        let sample = manager
            .create_sample(Duration::from_millis(150), true, 5)
            .await;

        assert_eq!(sample.analysis_duration_ms, 150);
        assert_eq!(sample.cache_hit_ratio, 1.0);
        assert_eq!(sample.queue_depth, 5);
    }

    #[tokio::test]
    async fn test_create_sample_cache_miss() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        let sample = manager
            .create_sample(Duration::from_millis(200), false, 0)
            .await;

        assert_eq!(sample.cache_hit_ratio, 0.0);
    }

    #[tokio::test]
    async fn test_high_queue_depth_adjustment() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 100,
            min_cache_hit_ratio: 0.5,
            sample_window_size: 15,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples with good cache hit but high queue depth and slow performance
        for _ in 0..15 {
            let sample = create_sample_full(180, 0.7, 100.0, 0.5, 10); // High queue depth
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should have increased permits due to high queue depth
        assert!(thresholds.high_priority_permits >= 10);
    }

    #[tokio::test]
    async fn test_less_compression_adjustment() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 50,
            min_cache_hit_ratio: 0.5,
            sample_window_size: 12,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples showing slow performance but good cache and low queue
        for _ in 0..15 {
            let sample = create_sample_full(150, 0.8, 100.0, 0.5, 2); // Slow, good cache, low queue
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should have reduced compression for speed
        // The compression_level should be adjusted to 1 (less compression)
        // But the exact value depends on the adjustment logic
        let _ = thresholds.compression_level; // Just verify no panic
    }

    #[tokio::test]
    async fn test_scale_down_high_memory() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 200,
            max_memory_mb: 100.0,
            sample_window_size: 12,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples with fast performance, high cache hit, but high memory
        for _ in 0..15 {
            let sample = create_sample_full(80, 0.95, 200.0, 0.4, 2); // Fast, high cache, high memory
            manager.record_sample(sample).await.unwrap();
        }

        // Should trigger scale down or more compression due to high memory
        let _thresholds = manager.get_current_thresholds().await;
    }

    #[tokio::test]
    async fn test_maintain_excellent_performance() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 100,
            max_memory_mb: 500.0,
            sample_window_size: 12,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples with excellent performance
        for _ in 0..15 {
            let sample = create_sample_full(40, 0.9, 200.0, 0.3, 1); // Very fast, high cache, low resource
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        // Should have recorded samples without major adjustments
        assert!(stats.total_samples > 0);
    }

    #[tokio::test]
    async fn test_trend_degrading() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add degrading trend samples (getting slower)
        for i in 0..20 {
            let duration = 100 + (i * 10); // Getting slower over time
            let sample = create_sample_full(duration, 0.7, 150.0, 0.5, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        assert!(matches!(
            stats.performance_trend,
            PerformanceTrend::Degrading
        ));
    }

    #[tokio::test]
    async fn test_trend_stable() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add stable performance samples
        for _ in 0..20 {
            let sample = create_sample_full(100, 0.7, 150.0, 0.5, 2); // Same duration each time
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        assert!(matches!(stats.performance_trend, PerformanceTrend::Stable));
    }

    #[tokio::test]
    async fn test_get_memory_usage() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let memory = manager.get_memory_usage().await;
        // Should be >= base memory (50.0)
        assert!(memory >= 50.0);
    }

    #[tokio::test]
    async fn test_get_cpu_usage() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let cpu = manager.get_cpu_usage().await;
        // Should be between 0 and 1
        assert!(cpu >= 0.0 && cpu <= 1.0);
    }

    #[tokio::test]
    async fn test_get_cpu_usage_with_samples() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add recent samples
        for _ in 0..5 {
            let sample = create_sample_full(100, 0.8, 200.0, 0.5, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let cpu = manager.get_cpu_usage().await;
        // Should reflect recent activity
        assert!(cpu >= 0.0 && cpu <= 1.0);
    }

    #[tokio::test]
    async fn test_get_performance_stats_empty() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());
        let stats = manager.get_performance_stats().await;

        assert_eq!(stats.total_samples, 0);
        assert_eq!(stats.avg_analysis_duration_ms, 0.0);
    }

    #[tokio::test]
    async fn test_scale_down_with_high_cpu() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 200,
            max_cpu_utilization: 0.5,
            max_memory_mb: 500.0,
            sample_window_size: 12,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add samples with high CPU but fast performance and high cache
        for _ in 0..15 {
            let sample = create_sample_full(80, 0.95, 200.0, 0.8, 2); // Fast, high cache, high CPU
            manager.record_sample(sample).await.unwrap();
        }

        // Should trigger adjustment due to high CPU
        let _thresholds = manager.get_current_thresholds().await;
    }

    #[tokio::test]
    async fn test_adjustment_history_limit() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 100,
            min_cache_hit_ratio: 0.9, // Hard to achieve
            sample_window_size: 10,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Add many samples to trigger many adjustments
        for _ in 0..200 {
            let sample = create_sample_full(200, 0.3, 100.0, 0.5, 2); // Triggers adjustments
            manager.record_sample(sample).await.unwrap();
        }

        // Adjustment history should be limited to 100
        let stats = manager.get_performance_stats().await;
        assert!(stats.recent_adjustments_count <= 100);
    }

    // =============================================================================
    // FACTORY TESTS
    // =============================================================================

    #[test]
    fn test_factory_create_default() {
        let manager = AdaptiveThresholdFactory::create_default();
        let _ = format!("{:?}", manager.config);
    }

    #[test]
    fn test_factory_create_dev_optimized() {
        let manager = AdaptiveThresholdFactory::create_dev_optimized();
        assert_eq!(manager.config.target_analysis_time_ms, 50);
        assert_eq!(manager.config.sample_window_size, 20);
        assert_eq!(manager.config.adjustment_sensitivity, 0.2);
    }

    #[test]
    fn test_factory_create_prod_optimized() {
        let manager = AdaptiveThresholdFactory::create_prod_optimized();
        assert_eq!(manager.config.target_analysis_time_ms, 200);
        assert_eq!(manager.config.sample_window_size, 100);
        assert_eq!(manager.config.adjustment_sensitivity, 0.05);
    }

    // =============================================================================
    // EDGE CASE TESTS
    // =============================================================================

    #[tokio::test]
    async fn test_insufficient_samples_for_adjustment() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add only 5 samples (below minimum for adjustment)
        for _ in 0..5 {
            let sample = create_sample_full(200, 0.3, 600.0, 0.9, 10);
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should still be at defaults since not enough samples
        assert_eq!(thresholds.hot_cache_size, 1000);
    }

    #[tokio::test]
    async fn test_insufficient_samples_for_trend() {
        let manager = AdaptiveThresholdManager::new(AdaptiveConfig::default());

        // Add only 5 samples
        for _ in 0..5 {
            let sample = create_sample_full(100, 0.8, 200.0, 0.5, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let stats = manager.get_performance_stats().await;
        // Should be stable since not enough samples for trend calculation
        assert!(matches!(stats.performance_trend, PerformanceTrend::Stable));
    }

    #[tokio::test]
    async fn test_scale_up_max_limits() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 50,
            min_cache_hit_ratio: 0.9,
            sample_window_size: 10,
            adjustment_sensitivity: 0.5, // Large adjustments
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Trigger many scale-ups
        for _ in 0..50 {
            let sample = create_sample_full(200, 0.3, 100.0, 0.3, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should be capped at max values
        assert!(thresholds.hot_cache_size <= 10000);
        assert!(thresholds.high_priority_permits <= 50);
        assert!(thresholds.low_priority_permits <= 20);
    }

    #[tokio::test]
    async fn test_scale_down_min_limits() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 500,
            max_memory_mb: 50.0, // Very low to trigger scale down
            max_cpu_utilization: 0.2,
            sample_window_size: 10,
            adjustment_sensitivity: 0.5,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Trigger many scale-downs
        for _ in 0..50 {
            let sample = create_sample_full(50, 0.95, 300.0, 0.9, 2); // Fast but resource heavy
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should be floored at min values
        assert!(thresholds.hot_cache_size >= 100);
        assert!(thresholds.high_priority_permits >= 2);
        assert!(thresholds.low_priority_permits >= 1);
    }

    #[tokio::test]
    async fn test_no_adjustment_moderate_performance() {
        // Exercise the Ok(None) return path in calculate_adjustment:
        // Performance is moderate (not slow enough for ScaleUp, not excellent enough for Maintain),
        // and resource usage is within limits (no ScaleDown/MoreCompression needed).
        let config = AdaptiveConfig {
            target_analysis_time_ms: 100,
            max_memory_mb: 512.0,
            max_cpu_utilization: 0.8,
            sample_window_size: 20,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // duration=80: NOT > 150 (target*1.5), so skip first block
        // memory=100 <= 512 and cpu=0.3 <= 0.8, so skip resource block
        // duration=80: NOT < 50 (target*0.5), so skip Maintain block
        // Result: Ok(None) -- no adjustment
        for _ in 0..15 {
            let sample = create_sample_full(80, 0.7, 100.0, 0.3, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Should remain at defaults since no adjustment was triggered
        assert_eq!(thresholds.hot_cache_size, 1000);
        assert_eq!(thresholds.compression_level, 4);
        assert_eq!(thresholds.high_priority_permits, 10);
    }

    #[tokio::test]
    async fn test_compression_level_bounds() {
        let config = AdaptiveConfig {
            target_analysis_time_ms: 10, // Very aggressive
            max_memory_mb: 1000.0,
            sample_window_size: 10,
            ..Default::default()
        };
        let manager = AdaptiveThresholdManager::new(config);

        // Trigger less compression adjustments
        for _ in 0..20 {
            let sample = create_sample_full(100, 0.8, 100.0, 0.3, 2);
            manager.record_sample(sample).await.unwrap();
        }

        let thresholds = manager.get_current_thresholds().await;
        // Compression level should be within valid range
        assert!(thresholds.compression_level >= 1);
        assert!(thresholds.compression_level <= 9);
    }
}
