//! Mock Services for Foxhunt HFT Trading System Testing
//!
//! This module provides mock implementations of all external services
//! for isolated testing without dependencies on real services.

use chrono::{DateTime, Utc};
use rust_decimal::Decimal;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::{mpsc, Mutex, RwLock};
use tokio::time::sleep;
use uuid::Uuid;

use super::test_config::TestConfig;

// =============================================================================
// MOCK TRADING SERVICE
// =============================================================================

/// Mock trading service for testing trading operations
#[derive(Debug, Clone)]
pub struct MockTradingService {
    _config: TestConfig,
    orders: Arc<RwLock<HashMap<Uuid, MockOrder>>>,
    positions: Arc<RwLock<HashMap<String, MockPosition>>>,
    order_events: Arc<Mutex<mpsc::UnboundedSender<MockOrderEvent>>>,
    latency_ms: u64,
    failure_rate: f64,
    next_order_id: Arc<RwLock<u64>>,
}

impl MockTradingService {
    pub fn new(config: TestConfig) -> Self {
        let (sender, _receiver) = mpsc::unbounded_channel();
        let latency_ms = config.services.mock_latency_ms;
        let failure_rate = config.services.mock_failure_rate;

        Self {
            latency_ms,
            failure_rate,
            _config: config,
            orders: Arc::new(RwLock::new(HashMap::new())),
            positions: Arc::new(RwLock::new(HashMap::new())),
            order_events: Arc::new(Mutex::new(sender)),
            next_order_id: Arc::new(RwLock::new(1)),
        }
    }

    /// Submit a new order
    pub async fn submit_order(
        &self,
        request: MockOrderRequest,
    ) -> Result<MockOrderResponse, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let order_id = {
            let mut next_id = self.next_order_id.write().await;
            let id = *next_id;
            *next_id += 1;
            id
        };

        let order = MockOrder {
            id: Uuid::new_v4(),
            order_id,
            symbol: request.symbol.clone(),
            side: request.side,
            quantity: request.quantity,
            price: request.price,
            order_type: request.order_type,
            status: MockOrderStatus::Pending,
            filled_quantity: Decimal::ZERO,
            average_fill_price: Decimal::ZERO,
            created_at: Utc::now(),
            updated_at: Utc::now(),
        };

        // Store the order
        self.orders.write().await.insert(order.id, order.clone());

        // Simulate order processing in background
        let service = self.clone();
        let order_id = order.id;
        tokio::spawn(async move {
            service.process_order(order_id).await;
        });

        Ok(MockOrderResponse {
            order_id: order.id,
            status: MockOrderStatus::Pending,
            message: "Order submitted successfully".to_string(),
        })
    }

    /// Cancel an existing order
    pub async fn cancel_order(
        &self,
        order_id: Uuid,
    ) -> Result<MockOrderResponse, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let mut orders = self.orders.write().await;
        if let Some(order) = orders.get_mut(&order_id) {
            if matches!(
                order.status,
                MockOrderStatus::Pending | MockOrderStatus::PartiallyFilled
            ) {
                order.status = MockOrderStatus::Cancelled;
                order.updated_at = Utc::now();

                Ok(MockOrderResponse {
                    order_id,
                    status: MockOrderStatus::Cancelled,
                    message: "Order cancelled successfully".to_string(),
                })
            } else {
                Err(MockServiceError::InvalidOperation(format!(
                    "Cannot cancel order in status: {:?}",
                    order.status
                )))
            }
        } else {
            Err(MockServiceError::OrderNotFound(order_id))
        }
    }

    /// Get order status
    pub async fn get_order_status(&self, order_id: Uuid) -> Result<MockOrder, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let orders = self.orders.read().await;
        orders
            .get(&order_id)
            .cloned()
            .ok_or(MockServiceError::OrderNotFound(order_id))
    }

    /// Get all orders for a symbol
    pub async fn get_orders_for_symbol(
        &self,
        symbol: &str,
    ) -> Result<Vec<MockOrder>, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let orders = self.orders.read().await;
        let filtered_orders: Vec<MockOrder> = orders
            .values()
            .filter(|order| order.symbol == symbol)
            .cloned()
            .collect();

        Ok(filtered_orders)
    }

    /// Get current positions
    pub async fn get_positions(&self) -> Result<Vec<MockPosition>, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let positions = self.positions.read().await;
        Ok(positions.values().cloned().collect())
    }

    /// Process order asynchronously (simulate fill)
    async fn process_order(&self, order_id: Uuid) {
        // Wait a bit before processing
        sleep(Duration::from_millis(100 + self.latency_ms)).await;

        let mut orders = self.orders.write().await;
        if let Some(order) = orders.get_mut(&order_id) {
            // Simulate partial fill first
            order.status = MockOrderStatus::PartiallyFilled;
            order.filled_quantity = order.quantity / Decimal::from(2); // Fill 50%
            order.average_fill_price = order.price;
            order.updated_at = Utc::now();

            // Send event
            self.send_order_event(order.clone()).await;

            // Wait a bit more
            drop(orders); // Release lock
            sleep(Duration::from_millis(200)).await;

            // Complete the fill
            let mut orders = self.orders.write().await;
            if let Some(order) = orders.get_mut(&order_id) {
                order.status = MockOrderStatus::Filled;
                order.filled_quantity = order.quantity;
                order.updated_at = Utc::now();

                // Update position
                self.update_position(order).await;

                // Send final event
                self.send_order_event(order.clone()).await;
            }
        }
    }

    /// Update position based on filled order
    async fn update_position(&self, order: &MockOrder) {
        let mut positions = self.positions.write().await;
        let position_key = order.symbol.clone();

        let position = positions
            .entry(position_key)
            .or_insert_with(|| MockPosition {
                symbol: order.symbol.clone(),
                quantity: Decimal::ZERO,
                average_price: Decimal::ZERO,
                market_value: Decimal::ZERO,
                unrealized_pnl: Decimal::ZERO,
                updated_at: Utc::now(),
            });

        // Update position quantity and average price
        let old_quantity = position.quantity;
        let old_value = old_quantity * position.average_price;

        let order_quantity = match order.side {
            MockOrderSide::Buy => order.filled_quantity,
            MockOrderSide::Sell => -order.filled_quantity,
        };

        let new_quantity = old_quantity + order_quantity;
        let order_value = order.filled_quantity * order.average_fill_price;

        if new_quantity != Decimal::ZERO {
            let new_total_value = match order.side {
                MockOrderSide::Buy => old_value + order_value,
                MockOrderSide::Sell => old_value - order_value,
            };
            position.average_price = new_total_value / new_quantity.abs();
        } else {
            position.average_price = Decimal::ZERO;
        }

        position.quantity = new_quantity;
        position.market_value = position.quantity * order.average_fill_price; // Assume market price = fill price
        position.unrealized_pnl =
            (order.average_fill_price - position.average_price) * position.quantity;
        position.updated_at = Utc::now();
    }

    /// Send order event
    async fn send_order_event(&self, order: MockOrder) {
        let event = MockOrderEvent {
            order_id: order.id,
            symbol: order.symbol,
            status: order.status,
            filled_quantity: order.filled_quantity,
            timestamp: Utc::now(),
        };

        if let Ok(sender) = self.order_events.try_lock() {
            let _ = sender.send(event);
        }
    }

    async fn simulate_latency(&self) {
        if self.latency_ms > 0 {
            sleep(Duration::from_millis(self.latency_ms)).await;
        }
    }

    fn simulate_failure(&self) -> Result<(), MockServiceError> {
        if self.failure_rate > 0.0 {
            use rand::Rng;
            let mut rng = rand::thread_rng();
            if rng.gen::<f64>() < self.failure_rate {
                return Err(MockServiceError::SimulatedFailure);
            }
        }
        Ok(())
    }
}

// =============================================================================
// MOCK ML TRAINING SERVICE
// =============================================================================

/// Mock ML training service for testing ML operations
#[derive(Debug, Clone)]
pub struct MockMLTrainingService {
    _config: TestConfig,
    training_jobs: Arc<RwLock<HashMap<Uuid, MockTrainingJob>>>,
    models: Arc<RwLock<HashMap<String, MockModel>>>,
    latency_ms: u64,
    failure_rate: f64,
}

impl MockMLTrainingService {
    pub fn new(config: TestConfig) -> Self {
        let latency_ms = config.services.mock_latency_ms;
        let failure_rate = config.services.mock_failure_rate;

        Self {
            latency_ms,
            failure_rate,
            _config: config,
            training_jobs: Arc::new(RwLock::new(HashMap::new())),
            models: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Start a new training job
    pub async fn start_training(
        &self,
        request: MockTrainingRequest,
    ) -> Result<MockTrainingResponse, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let job_id = Uuid::new_v4();
        let job = MockTrainingJob {
            id: job_id,
            model_name: request.model_name.clone(),
            model_type: request.model_type,
            status: MockTrainingStatus::Running,
            progress: 0.0,
            start_time: Utc::now(),
            end_time: None,
            metrics: HashMap::new(),
            error_message: None,
        };

        self.training_jobs.write().await.insert(job_id, job.clone());

        // Simulate training in background
        let service = self.clone();
        tokio::spawn(async move {
            service.simulate_training(job_id).await;
        });

        Ok(MockTrainingResponse {
            job_id,
            status: MockTrainingStatus::Running,
            message: "Training job started".to_string(),
        })
    }

    /// Get training job status
    pub async fn get_training_status(
        &self,
        job_id: Uuid,
    ) -> Result<MockTrainingJob, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let jobs = self.training_jobs.read().await;
        jobs.get(&job_id)
            .cloned()
            .ok_or(MockServiceError::JobNotFound(job_id))
    }

    /// Get available models
    pub async fn get_models(&self) -> Result<Vec<MockModel>, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let models = self.models.read().await;
        Ok(models.values().cloned().collect())
    }

    /// Run inference with a model
    pub async fn run_inference(
        &self,
        request: MockInferenceRequest,
    ) -> Result<MockInferenceResponse, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        // Simulate inference calculation
        let prediction = match request.model_name.as_str() {
            "momentum_model" => 0.75,        // Bullish
            "mean_reversion_model" => -0.25, // Bearish
            _ => 0.0,                        // Neutral
        };

        Ok(MockInferenceResponse {
            prediction,
            confidence: 0.85,
            features_used: request.features.len(),
            inference_time_ms: self.latency_ms,
        })
    }

    /// Simulate training process
    async fn simulate_training(&self, job_id: Uuid) {
        let training_duration = Duration::from_secs(5); // Simulate 5 second training
        let update_interval = Duration::from_millis(500);
        let total_updates = training_duration.as_millis() / update_interval.as_millis();

        for i in 0..total_updates {
            sleep(update_interval).await;

            let progress = (i as f64 + 1.0) / total_updates as f64;

            // Update job progress
            if let Ok(mut jobs) = self.training_jobs.try_write() {
                if let Some(job) = jobs.get_mut(&job_id) {
                    job.progress = progress;

                    // Add some metrics
                    job.metrics
                        .insert("loss".to_string(), 1.0 - (progress * 0.8));
                    job.metrics
                        .insert("accuracy".to_string(), 0.5 + (progress * 0.4));

                    if progress >= 1.0 {
                        job.status = MockTrainingStatus::Completed;
                        job.end_time = Some(Utc::now());

                        // Save the trained model
                        let model = MockModel {
                            name: job.model_name.clone(),
                            model_type: job.model_type,
                            version: "1.0.0".to_string(),
                            accuracy: job.metrics.get("accuracy").copied().unwrap_or(0.9),
                            created_at: Utc::now(),
                            file_path: format!("/models/{}_v1.0.0.bin", job.model_name),
                        };

                        if let Ok(mut models) = self.models.try_write() {
                            models.insert(model.name.clone(), model);
                        }
                    }
                }
            }
        }
    }

    async fn simulate_latency(&self) {
        if self.latency_ms > 0 {
            sleep(Duration::from_millis(self.latency_ms)).await;
        }
    }

    fn simulate_failure(&self) -> Result<(), MockServiceError> {
        if self.failure_rate > 0.0 {
            use rand::Rng;
            let mut rng = rand::thread_rng();
            if rng.gen::<f64>() < self.failure_rate {
                return Err(MockServiceError::SimulatedFailure);
            }
        }
        Ok(())
    }
}

// =============================================================================
// MOCK BACKTESTING SERVICE
// =============================================================================

/// Mock backtesting service for testing strategy backtests
#[derive(Debug, Clone)]
pub struct MockBacktestingService {
    _config: TestConfig,
    backtests: Arc<RwLock<HashMap<Uuid, MockBacktest>>>,
    latency_ms: u64,
    failure_rate: f64,
}

impl MockBacktestingService {
    pub fn new(config: TestConfig) -> Self {
        let latency_ms = config.services.mock_latency_ms;
        let failure_rate = config.services.mock_failure_rate;

        Self {
            latency_ms,
            failure_rate,
            _config: config,
            backtests: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Start a new backtest
    pub async fn start_backtest(
        &self,
        request: MockBacktestRequest,
    ) -> Result<MockBacktestResponse, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let backtest_id = Uuid::new_v4();
        let backtest = MockBacktest {
            id: backtest_id,
            strategy_name: request.strategy_name.clone(),
            symbols: request.symbols,
            start_date: request.start_date,
            end_date: request.end_date,
            status: MockBacktestStatus::Running,
            progress: 0.0,
            results: None,
            start_time: Utc::now(),
            end_time: None,
        };

        self.backtests.write().await.insert(backtest_id, backtest);

        // Simulate backtest in background
        let service = self.clone();
        tokio::spawn(async move {
            service.simulate_backtest(backtest_id).await;
        });

        Ok(MockBacktestResponse {
            backtest_id,
            status: MockBacktestStatus::Running,
            message: "Backtest started".to_string(),
        })
    }

    /// Get backtest status
    pub async fn get_backtest_status(
        &self,
        backtest_id: Uuid,
    ) -> Result<MockBacktest, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let backtests = self.backtests.read().await;
        backtests
            .get(&backtest_id)
            .cloned()
            .ok_or(MockServiceError::BacktestNotFound(backtest_id))
    }

    /// Get all backtests
    pub async fn get_backtests(&self) -> Result<Vec<MockBacktest>, MockServiceError> {
        self.simulate_latency().await;
        self.simulate_failure()?;

        let backtests = self.backtests.read().await;
        Ok(backtests.values().cloned().collect())
    }

    /// Simulate backtest process
    async fn simulate_backtest(&self, backtest_id: Uuid) {
        let backtest_duration = Duration::from_secs(3); // Simulate 3 second backtest
        let update_interval = Duration::from_millis(300);
        let total_updates = backtest_duration.as_millis() / update_interval.as_millis();

        for i in 0..total_updates {
            sleep(update_interval).await;

            let progress = (i as f64 + 1.0) / total_updates as f64;

            if let Ok(mut backtests) = self.backtests.try_write() {
                if let Some(backtest) = backtests.get_mut(&backtest_id) {
                    backtest.progress = progress;

                    if progress >= 1.0 {
                        backtest.status = MockBacktestStatus::Completed;
                        backtest.end_time = Some(Utc::now());

                        // Generate mock results
                        backtest.results = Some(MockBacktestResults {
                            total_return: 0.15, // 15% return
                            annualized_return: 0.12,
                            volatility: 0.18,
                            sharpe_ratio: 0.67,
                            max_drawdown: 0.08,
                            win_rate: 0.58,
                            total_trades: 1250,
                            profit_factor: 1.35,
                        });
                    }
                }
            }
        }
    }

    async fn simulate_latency(&self) {
        if self.latency_ms > 0 {
            sleep(Duration::from_millis(self.latency_ms)).await;
        }
    }

    fn simulate_failure(&self) -> Result<(), MockServiceError> {
        if self.failure_rate > 0.0 {
            use rand::Rng;
            let mut rng = rand::thread_rng();
            if rng.gen::<f64>() < self.failure_rate {
                return Err(MockServiceError::SimulatedFailure);
            }
        }
        Ok(())
    }
}

// =============================================================================
// DATA STRUCTURES
// =============================================================================

/// Mock order structure
#[derive(Debug, Clone)]
pub struct MockOrder {
    pub id: Uuid,
    pub order_id: u64,
    pub symbol: String,
    pub side: MockOrderSide,
    pub quantity: Decimal,
    pub price: Decimal,
    pub order_type: MockOrderType,
    pub status: MockOrderStatus,
    pub filled_quantity: Decimal,
    pub average_fill_price: Decimal,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockOrderSide {
    Buy,
    Sell,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockOrderType {
    Market,
    Limit,
    Stop,
    StopLimit,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockOrderStatus {
    Pending,
    PartiallyFilled,
    Filled,
    Cancelled,
    Rejected,
}

/// Mock position structure
#[derive(Debug, Clone)]
pub struct MockPosition {
    pub symbol: String,
    pub quantity: Decimal,
    pub average_price: Decimal,
    pub market_value: Decimal,
    pub unrealized_pnl: Decimal,
    pub updated_at: DateTime<Utc>,
}

/// Mock order request
#[derive(Debug, Clone)]
pub struct MockOrderRequest {
    pub symbol: String,
    pub side: MockOrderSide,
    pub quantity: Decimal,
    pub price: Decimal,
    pub order_type: MockOrderType,
}

/// Mock order response
#[derive(Debug, Clone)]
pub struct MockOrderResponse {
    pub order_id: Uuid,
    pub status: MockOrderStatus,
    pub message: String,
}

/// Mock order event
#[derive(Debug, Clone)]
pub struct MockOrderEvent {
    pub order_id: Uuid,
    pub symbol: String,
    pub status: MockOrderStatus,
    pub filled_quantity: Decimal,
    pub timestamp: DateTime<Utc>,
}

/// Mock training job
#[derive(Debug, Clone)]
pub struct MockTrainingJob {
    pub id: Uuid,
    pub model_name: String,
    pub model_type: MockModelType,
    pub status: MockTrainingStatus,
    pub progress: f64,
    pub start_time: DateTime<Utc>,
    pub end_time: Option<DateTime<Utc>>,
    pub metrics: HashMap<String, f64>,
    pub error_message: Option<String>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockModelType {
    Mamba,
    Transformer,
    DQN,
    PPO,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockTrainingStatus {
    Running,
    Completed,
    Failed,
    Cancelled,
}

/// Mock model
#[derive(Debug, Clone)]
pub struct MockModel {
    pub name: String,
    pub model_type: MockModelType,
    pub version: String,
    pub accuracy: f64,
    pub created_at: DateTime<Utc>,
    pub file_path: String,
}

/// Mock training request
#[derive(Debug, Clone)]
pub struct MockTrainingRequest {
    pub model_name: String,
    pub model_type: MockModelType,
    pub data_path: String,
    pub hyperparameters: HashMap<String, serde_json::Value>,
}

/// Mock training response
#[derive(Debug, Clone)]
pub struct MockTrainingResponse {
    pub job_id: Uuid,
    pub status: MockTrainingStatus,
    pub message: String,
}

/// Mock inference request
#[derive(Debug, Clone)]
pub struct MockInferenceRequest {
    pub model_name: String,
    pub features: Vec<f64>,
}

/// Mock inference response
#[derive(Debug, Clone)]
pub struct MockInferenceResponse {
    pub prediction: f64,
    pub confidence: f64,
    pub features_used: usize,
    pub inference_time_ms: u64,
}

/// Mock backtest
#[derive(Debug, Clone)]
pub struct MockBacktest {
    pub id: Uuid,
    pub strategy_name: String,
    pub symbols: Vec<String>,
    pub start_date: DateTime<Utc>,
    pub end_date: DateTime<Utc>,
    pub status: MockBacktestStatus,
    pub progress: f64,
    pub results: Option<MockBacktestResults>,
    pub start_time: DateTime<Utc>,
    pub end_time: Option<DateTime<Utc>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockBacktestStatus {
    Running,
    Completed,
    Failed,
    Cancelled,
}

/// Mock backtest results
#[derive(Debug, Clone)]
pub struct MockBacktestResults {
    pub total_return: f64,
    pub annualized_return: f64,
    pub volatility: f64,
    pub sharpe_ratio: f64,
    pub max_drawdown: f64,
    pub win_rate: f64,
    pub total_trades: u64,
    pub profit_factor: f64,
}

/// Mock backtest request
#[derive(Debug, Clone)]
pub struct MockBacktestRequest {
    pub strategy_name: String,
    pub symbols: Vec<String>,
    pub start_date: DateTime<Utc>,
    pub end_date: DateTime<Utc>,
    pub initial_capital: Decimal,
}

/// Mock backtest response
#[derive(Debug, Clone)]
pub struct MockBacktestResponse {
    pub backtest_id: Uuid,
    pub status: MockBacktestStatus,
    pub message: String,
}

/// Mock service errors
#[derive(Debug, Clone, thiserror::Error)]
pub enum MockServiceError {
    #[error("Order not found: {0}")]
    OrderNotFound(Uuid),

    #[error("Job not found: {0}")]
    JobNotFound(Uuid),

    #[error("Backtest not found: {0}")]
    BacktestNotFound(Uuid),

    #[error("Invalid operation: {0}")]
    InvalidOperation(String),

    #[error("Simulated failure")]
    SimulatedFailure,

    #[error("Service unavailable")]
    ServiceUnavailable,
}

// =============================================================================
// SERVICE FACTORY
// =============================================================================

/// Factory for creating mock services
#[derive(Debug)]
pub struct MockServiceFactory {
    config: TestConfig,
}

impl MockServiceFactory {
    pub fn new(config: TestConfig) -> Self {
        Self { config }
    }

    pub fn create_trading_service(&self) -> MockTradingService {
        MockTradingService::new(self.config.clone())
    }

    pub fn create_ml_training_service(&self) -> MockMLTrainingService {
        MockMLTrainingService::new(self.config.clone())
    }

    pub fn create_backtesting_service(&self) -> MockBacktestingService {
        MockBacktestingService::new(self.config.clone())
    }

    /// Create all services
    pub fn create_all_services(
        &self,
    ) -> (
        MockTradingService,
        MockMLTrainingService,
        MockBacktestingService,
    ) {
        (
            self.create_trading_service(),
            self.create_ml_training_service(),
            self.create_backtesting_service(),
        )
    }
}

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

    #[tokio::test]
    async fn test_mock_trading_service() {
        let config = TestConfig::for_unit_tests();
        let service = MockTradingService::new(config);

        let request = MockOrderRequest {
            symbol: TEST_EQUITY_1.to_string(),
            side: MockOrderSide::Buy,
            quantity: Decimal::from(100),
            price: Decimal::from(150),
            order_type: MockOrderType::Limit,
        };

        let response = service.submit_order(request).await.unwrap();
        assert_eq!(response.status, MockOrderStatus::Pending);

        // Wait for processing
        tokio::time::sleep(Duration::from_millis(500)).await;

        let order = service.get_order_status(response.order_id).await.unwrap();
        assert_eq!(order.status, MockOrderStatus::Filled);
        assert_eq!(order.filled_quantity, order.quantity);
    }

    #[tokio::test]
    async fn test_mock_ml_training_service() {
        let config = TestConfig::for_unit_tests();
        let service = MockMLTrainingService::new(config);

        let request = MockTrainingRequest {
            model_name: "test_model".to_string(),
            model_type: MockModelType::Transformer,
            data_path: "/data/test.csv".to_string(),
            hyperparameters: HashMap::new(),
        };

        let response = service.start_training(request).await.unwrap();
        assert_eq!(response.status, MockTrainingStatus::Running);

        // Wait for training to complete
        tokio::time::sleep(Duration::from_secs(6)).await;

        let job = service.get_training_status(response.job_id).await.unwrap();
        assert_eq!(job.status, MockTrainingStatus::Completed);
        assert_eq!(job.progress, 1.0);
    }

    #[tokio::test]
    async fn test_mock_backtesting_service() {
        let config = TestConfig::for_unit_tests();
        let service = MockBacktestingService::new(config);

        let request = MockBacktestRequest {
            strategy_name: "test_strategy".to_string(),
            symbols: vec![TEST_EQUITY_1.to_string()],
            start_date: Utc::now() - chrono::Duration::days(30),
            end_date: Utc::now(),
            initial_capital: Decimal::from(100000),
        };

        let response = service.start_backtest(request).await.unwrap();
        assert_eq!(response.status, MockBacktestStatus::Running);

        // Wait for backtest to complete
        tokio::time::sleep(Duration::from_secs(4)).await;

        let backtest = service
            .get_backtest_status(response.backtest_id)
            .await
            .unwrap();
        assert_eq!(backtest.status, MockBacktestStatus::Completed);
        assert!(backtest.results.is_some());
    }

    #[tokio::test]
    async fn test_service_factory() {
        let config = TestConfig::for_unit_tests();
        let factory = MockServiceFactory::new(config);

        let (trading, ml, backtesting) = factory.create_all_services();

        // Test that all services are created
        assert_eq!(trading.latency_ms, 0);
        assert_eq!(ml.latency_ms, 0);
        assert_eq!(backtesting.latency_ms, 0);
    }

    #[tokio::test]
    async fn test_failure_simulation() {
        let mut config = TestConfig::for_unit_tests();
        config.services.mock_failure_rate = 1.0; // 100% failure rate

        let service = MockTradingService::new(config);

        let request = MockOrderRequest {
            symbol: TEST_EQUITY_1.to_string(),
            side: MockOrderSide::Buy,
            quantity: Decimal::from(100),
            price: Decimal::from(150),
            order_type: MockOrderType::Limit,
        };

        let result = service.submit_order(request).await;
        assert!(result.is_err());
        assert!(matches!(
            result.unwrap_err(),
            MockServiceError::SimulatedFailure
        ));
    }
}
