//! # Enhanced ML Integration Hub
//!
//! Realistic and optimized ML integration architecture for Foxhunt HFT system.
//! Based on expert consensus analysis, this module implements a practical approach
//! that balances performance requirements with technical feasibility.

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

use tokio::sync::RwLock;

use super::*;
use crate::MLError;

// Re-export integration submodules
pub mod coordinator;
pub mod distillation;
pub mod inference_engine;
pub mod model_registry;
pub mod performance_monitor;
pub mod strategy_dqn_bridge;

/// Configuration for ML Integration Hub
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct IntegrationHubConfig {
    /// Maximum number of concurrent models
    pub max_concurrent_models: usize,
    /// Default inference timeout in milliseconds
    pub default_timeout_ms: u64,
    /// Enable performance monitoring
    pub enable_monitoring: bool,
    /// Model cache size
    pub cache_size: usize,
}

impl Default for IntegrationHubConfig {
    fn default() -> Self {
        Self {
            max_concurrent_models: 5,
            default_timeout_ms: 1000,
            enable_monitoring: true,
            cache_size: 100,
        }
    }
}

/// ML Integration Hub for coordinating model operations
#[derive(Debug)]
pub struct MLIntegrationHub {
    config: IntegrationHubConfig,
    active_models: Arc<RwLock<HashMap<String, String>>>,
}

impl MLIntegrationHub {
    /// Create new ML Integration Hub
    pub async fn new(config: IntegrationHubConfig) -> Result<Self, MLError> {
        Ok(Self {
            config,
            active_models: Arc::new(RwLock::new(HashMap::new())),
        })
    }

    /// Get configuration
    pub fn config(&self) -> &IntegrationHubConfig {
        &self.config
    }
}

/// Model deployment configuration
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ModelDeployment {
    /// Unique model identifier
    pub model_id: String,
    /// Model type
    pub model_type: ModelType,
    /// Model version
    pub version: String,
    /// Serving modes
    pub serving_modes: Vec<ServingMode>,
    /// File path to model
    pub file_path: String,
    /// Target latency in microseconds
    pub target_latency_us: u64,
    /// Memory requirement in MB
    pub memory_requirement_mb: usize,
    /// Compute unit (CPU/`GPU`)
    pub compute_unit: String,
    /// Warm up samples
    pub warm_up_samples: usize,
}

/// Model serving modes
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum ServingMode {
    /// Ultra-low latency serving
    UltraLowLatency,
    /// Low latency serving
    LowLatency,
    /// High throughput serving
    HighThroughput,
}

/// Model state
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum ModelState {
    /// Model is loading
    Loading,
    /// Model is active and ready
    Active,
    /// Model is inactive
    Inactive,
    /// Model has failed
    Failed,
}

// Use canonical ModelType from crate root
// DO NOT RE-EXPORT - Use explicit imports at usage sites

/// Model search criteria
#[derive(Debug, Clone)]
pub struct ModelSearchCriteria {
    /// Optional model type filter
    pub model_type: Option<ModelType>,
    /// Optional serving mode filter
    pub serving_mode: Option<ServingMode>,
    /// Maximum latency in microseconds
    pub max_latency_us: Option<u64>,
    /// Minimum accuracy threshold
    pub min_accuracy: Option<f64>,
    /// Search tags
    pub tags: Vec<String>,
    /// Status filter
    pub status: Option<ModelState>,
}

/// Model status information
#[derive(Debug, Clone)]
pub struct ModelStatus {
    /// Model identifier
    pub model_id: String,
    /// Current state
    pub status: ModelState,
    /// Last health check time
    pub last_health_check: SystemTime,
    /// Deployment time
    pub deployment_time: SystemTime,
    /// Inference count
    pub inference_count: u64,
    /// Error count
    pub error_count: u64,
    /// Average latency in microseconds
    pub avg_latency_us: f64,
    /// Memory usage in MB
    pub memory_usage_mb: f64,
    /// CPU utilization percentage
    pub cpu_utilization: f64,
}

/// Inference priority levels
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
pub enum InferencePriority {
    /// Critical priority
    Critical = 0,
    /// High priority
    High = 1,
    /// Medium priority
    Medium = 2,
    /// Low priority
    Low = 3,
}

#[tokio::test]
async fn test_integration_hub_creation() {
    let config = IntegrationHubConfig::default();
    let hub = MLIntegrationHub::new(config).await;
    assert!(hub.is_ok());
}

#[test]
fn test_model_type_serialization() -> Result<(), MLError> {
    let model_type = ModelType::DistilledMicroNet;
    let serialized =
        serde_json::to_string(&model_type).map_err(|e| MLError::SerializationError {
            reason: e.to_string(),
        })?;
    let deserialized: ModelType =
        serde_json::from_str(&serialized).map_err(|e| MLError::SerializationError {
            reason: e.to_string(),
        })?;
    assert_eq!(model_type, deserialized);
    Ok(())
}

#[test]
fn test_inference_priority_ordering() {
    assert!(InferencePriority::Critical < InferencePriority::High);
    assert!(InferencePriority::High < InferencePriority::Medium);
    assert!(InferencePriority::Medium < InferencePriority::Low);
}
