//! High-performance signal aggregation with SIMD optimization
//!
//! Ensemble aggregation for ML model predictions.

use std::collections::HashMap;
use std::sync::Arc;

use parking_lot::RwLock;
use serde::{Deserialize, Serialize};

use crate::confidence::ConfidenceCalculator;
use crate::weights::ModelWeights;
use crate::MLError;

/// Model signal structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelSignal {
    pub model_id: String,
    pub signal: f32,
    pub confidence: f32,
    pub timestamp: u64,
    pub metadata: SignalMetadata,
}

/// Signal metadata
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SignalMetadata {
    pub model_version: String,
    pub features_used: Vec<String>,
    pub prediction_horizon: u32,
}

/// Signal statistics
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SignalStatistics {
    pub total_signals: u64,
    pub avg_confidence: f32,
    pub accuracy_rate: f32,
    pub last_updated: u64,
}

/// Signal aggregator configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregatorConfig {
    pub max_signals: usize,
    pub confidence_threshold: f32,
    pub enable_simd: bool,
}

impl Default for AggregatorConfig {
    fn default() -> Self {
        Self {
            max_signals: 100,
            confidence_threshold: 0.5,
            enable_simd: true,
        }
    }
}

/// Main signal aggregator
#[derive(Debug)]
pub struct SignalAggregator {
    config: AggregatorConfig,
    weights: ModelWeights,
    confidence_calc: ConfidenceCalculator,
    stats: Arc<RwLock<HashMap<String, SignalStatistics>>>,
}

impl SignalAggregator {
    pub fn new(
        config: AggregatorConfig,
        weights: ModelWeights,
        confidence_calc: ConfidenceCalculator,
    ) -> Self {
        Self {
            config,
            weights,
            confidence_calc,
            stats: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    pub fn aggregate_signals(&self, signals: Vec<ModelSignal>) -> Result<f32, MLError> {
        if signals.is_empty() {
            return Ok(0.0);
        }

        // Simple weighted average for now
        let mut weighted_sum = 0.0;
        let mut total_weight = 0.0;

        for signal in &signals {
            if signal.confidence >= self.config.confidence_threshold {
                let weight = 1.0; // Simplified - should use actual weights
                weighted_sum += signal.signal * weight;
                total_weight += weight;
            }
        }

        if total_weight > 0.0 {
            Ok(weighted_sum / total_weight)
        } else {
            Ok(0.0)
        }
    }
}
