#![allow(
    clippy::tests_outside_test_module,
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::indexing_slicing,
    clippy::str_to_string,
    clippy::string_to_string,
    clippy::assertions_on_result_states,
    clippy::assertions_on_constants,
    clippy::let_underscore_must_use,
    clippy::use_debug,
    clippy::doc_markdown,
    clippy::shadow_unrelated,
    clippy::shadow_reuse,
    clippy::similar_names,
    clippy::clone_on_copy,
    clippy::get_unwrap,
    clippy::modulo_arithmetic,
    clippy::integer_division,
    clippy::non_ascii_literal,
    clippy::useless_vec,
    clippy::useless_format,
    clippy::wildcard_enum_match_arm,
    clippy::manual_range_contains,
    clippy::const_is_empty,
    clippy::needless_range_loop,
    clippy::field_reassign_with_default,
    clippy::items_after_test_module,
    clippy::missing_const_for_fn,
    unused_imports,
    unused_variables,
    unused_mut,
    unused_assignments,
    unused_comparisons,
    unused_must_use,
    dead_code,
)]
//! Trading Engine Integration Tests
//!
//! Comprehensive test coverage for the core trading engine
//! Tests the full flow: order submission -> validation -> execution -> position updates

use chrono::Utc;
use common::{MarketDataEvent, OrderId, OrderSide, OrderStatus, OrderType};
use rust_decimal::Decimal;
use std::sync::Arc;
use tokio::sync::{broadcast, RwLock};
use trading_engine::trading::data_interface::{DataProvider, Subscription};
use trading_engine::trading::engine::TradingEngine;
use trading_engine::trading_operations::{ExecutionResult, LiquidityFlag};

// ============================================================================
// Mock Data Provider for Testing
// ============================================================================

#[derive(Debug, Clone)]
struct MockDataProvider {
    market_data_tx: broadcast::Sender<MarketDataEvent>,
    order_update_tx: broadcast::Sender<MarketDataEvent>,
    subscriptions: Arc<RwLock<Vec<Subscription>>>,
}

impl MockDataProvider {
    fn new() -> Self {
        let (market_data_tx, _) = broadcast::channel(1000);
        let (order_update_tx, _) = broadcast::channel(1000);

        Self {
            market_data_tx,
            order_update_tx,
            subscriptions: Arc::new(RwLock::new(Vec::new())),
        }
    }
}

#[async_trait::async_trait]
impl DataProvider for MockDataProvider {
    async fn subscribe_market_data(&self, subscription: Subscription) -> Result<(), String> {
        self.subscriptions.write().await.push(subscription);
        Ok(())
    }

    fn subscribe_market_data_events(&self) -> broadcast::Receiver<MarketDataEvent> {
        self.market_data_tx.subscribe()
    }

    fn subscribe_order_update_events(&self) -> broadcast::Receiver<MarketDataEvent> {
        self.order_update_tx.subscribe()
    }
}

// ============================================================================
// Helper Functions
// ============================================================================

fn create_test_engine() -> TradingEngine {
    let data_provider = Arc::new(MockDataProvider::new());
    TradingEngine::new(data_provider)
}

fn create_execution(
    order_id: OrderId,
    symbol: &str,
    quantity: i64,
    price: i64,
) -> ExecutionResult {
    ExecutionResult {
        order_id,
        symbol: symbol.to_string(),
        side: OrderSide::Buy,
        executed_quantity: Decimal::from(quantity),
        execution_price: Decimal::from(price),
        execution_time: Utc::now(),
        commission: Decimal::from(10),
        liquidity_flag: LiquidityFlag::Maker,
    }
}

// ============================================================================
// Order Submission Tests (10 scenarios)
// Note: These test validation logic before broker submission
// ============================================================================

#[tokio::test]
async fn test_submit_market_order_buy_validation() {
    let engine = create_test_engine();

    // This will validate and create the order, but fail at broker submission
    // which is expected without a configured broker
    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await;

    // Should fail because no broker is configured, but this proves validation passed
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("broker"));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_submit_limit_order_sell() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Sell,
            OrderType::Limit,
            Decimal::from(10),
            Some(Decimal::from(3000)),
            None,
        )
        .await;

    assert!(result.is_ok());
}

#[tokio::test]
async fn test_submit_order_zero_quantity_rejected() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::ZERO,
            None,
            None,
        )
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("positive"));
}

#[tokio::test]
async fn test_submit_order_negative_quantity_rejected() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(-10),
            None,
            None,
        )
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("positive"));
}

#[tokio::test]
async fn test_submit_limit_order_zero_price_rejected() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(1),
            Some(Decimal::ZERO),
            None,
        )
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("price"));
}

#[tokio::test]
async fn test_submit_order_empty_symbol_rejected() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("symbol"));
}

#[tokio::test]
async fn test_submit_order_exceeds_buying_power() {
    let engine = create_test_engine();

    // Try to buy 10 BTC at 50k each (500k total) - exceeds demo account 100k buying power
    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            Some(Decimal::from(50000)),
            None,
        )
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("buying power"));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_submit_multiple_orders_same_symbol() {
    let engine = create_test_engine();

    let result1 = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            Some(Decimal::from(50000)),
            None,
        )
        .await;

    let result2 = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Sell,
            OrderType::Limit,
            Decimal::from(1),
            Some(Decimal::from(51000)),
            None,
        )
        .await;

    assert!(result1.is_ok());
    assert!(result2.is_ok());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_submit_orders_different_symbols() {
    let engine = create_test_engine();

    let btc_result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await;

    let eth_result = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await;

    assert!(btc_result.is_ok());
    assert!(eth_result.is_ok());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_submit_order_within_buying_power_boundary() {
    let engine = create_test_engine();

    // Exactly at buying power limit (2 * 50000 = 100000)
    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(2),
            Some(Decimal::from(50000)),
            None,
        )
        .await;

    assert!(result.is_ok());
}

// ============================================================================
// Order Cancellation Tests (5 scenarios)
// ============================================================================

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_cancel_pending_order() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(1),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    let result = engine.cancel_order(order_id).await;
    assert!(result.is_ok());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_cancel_filled_order_rejected() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    // Simulate fill
    let execution = create_execution(order_id, "BTCUSD", 1, 50000);
    let _ = engine.process_execution(execution).await;

    // Try to cancel filled order
    let result = engine.cancel_order(order_id).await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("filled"));
}

#[tokio::test]
async fn test_cancel_nonexistent_order() {
    let engine = create_test_engine();
    let fake_order_id: OrderId = "nonexistent".to_string().into();

    let result = engine.cancel_order(fake_order_id).await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("not found"));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_cancel_partially_filled_order() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(10),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // Partial fill (5 out of 10)
    let execution = create_execution(order_id, "BTCUSD", 5, 50000);
    let _ = engine.process_execution(execution).await;

    // Should be able to cancel partially filled order
    let result = engine.cancel_order(order_id).await;
    assert!(result.is_ok());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_get_order_status_after_submission() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(1),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    let order = engine.get_order_status(order_id).await;
    assert!(order.is_ok());

    let order_data = order.unwrap();
    assert_eq!(order_data.symbol, "BTCUSD");
    assert_eq!(order_data.quantity, Decimal::from(1));
}

// ============================================================================
// Fill Processing Tests (8 scenarios)
// ============================================================================

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_process_full_execution() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = create_execution(order_id, "BTCUSD", 1, 50000);
    let result = engine.process_execution(execution).await;
    assert!(result.is_ok());

    // Verify order status is Filled
    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.status, OrderStatus::Filled);
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_process_partial_execution() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(10),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // First partial fill
    let execution1 = create_execution(order_id, "BTCUSD", 3, 50000);
    engine
        .process_execution(execution1)
        .await
        .expect("First execution should succeed");

    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.status, OrderStatus::PartiallyFilled);
    assert_eq!(order.fill_quantity, Decimal::from(3));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_process_multiple_partial_fills() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(100),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // Multiple partial fills
    let execution1 = create_execution(order_id, "BTCUSD", 30, 50000);
    engine.process_execution(execution1).await.unwrap();

    let execution2 = create_execution(order_id, "BTCUSD", 40, 50100);
    engine.process_execution(execution2).await.unwrap();

    let execution3 = create_execution(order_id, "BTCUSD", 30, 49900);
    engine.process_execution(execution3).await.unwrap();

    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.status, OrderStatus::Filled);
    assert_eq!(order.fill_quantity, Decimal::from(100));

    // Check weighted average price
    let expected_avg = (Decimal::from(30) * Decimal::from(50000)
        + Decimal::from(40) * Decimal::from(50100)
        + Decimal::from(30) * Decimal::from(49900))
        / Decimal::from(100);

    assert_eq!(order.average_fill_price, Some(expected_avg));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_execution_updates_position() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = create_execution(order_id, "ETHUSD", 10, 3000);
    engine.process_execution(execution).await.unwrap();

    // Check position was created
    let positions = engine.get_positions(Some("ETHUSD".to_string())).await;
    assert!(positions.is_ok());

    let pos_list = positions.unwrap();
    assert_eq!(pos_list.len(), 1);
    assert_eq!(pos_list[0].quantity, Decimal::from(10));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_execution_updates_account_balance() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = ExecutionResult {
        order_id,
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Buy,
        executed_quantity: Decimal::from(1),
        execution_price: Decimal::from(50000),
        execution_time: Utc::now(),
        commission: Decimal::from(25), // $25 commission
        liquidity_flag: LiquidityFlag::Taker,
    };

    engine.process_execution(execution).await.unwrap();

    // Account should be updated (execution value + commission deducted)
    let account = engine
        .get_account_info("DEMO_ACCOUNT".to_string())
        .await
        .unwrap();

    // Buy: cash -= (1 * 50000) + 25 = 50025
    assert_eq!(
        account.cash_balance,
        Decimal::from(50000) - Decimal::from(50025)
    );
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_execution_with_slippage() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(1),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // Execute at worse price (slippage)
    let execution = create_execution(order_id, "BTCUSD", 1, 50100);
    let result = engine.process_execution(execution).await;
    assert!(result.is_ok());

    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.average_fill_price, Some(Decimal::from(50100)));
}

#[tokio::test]
async fn test_execution_for_nonexistent_order() {
    let engine = create_test_engine();

    let fake_order_id: OrderId = "nonexistent".to_string().into();
    let execution = create_execution(fake_order_id, "BTCUSD", 1, 50000);

    let result = engine.process_execution(execution).await;
    assert!(result.is_err());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_execution_creates_position_if_not_exists() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "SOLUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(100),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = create_execution(order_id, "SOLUSD", 100, 150);
    engine.process_execution(execution).await.unwrap();

    let positions = engine.get_positions(Some("SOLUSD".to_string())).await;
    assert!(positions.is_ok());

    let pos_list = positions.unwrap();
    assert_eq!(pos_list.len(), 1);
    assert_eq!(pos_list[0].symbol.to_string(), "SOLUSD");
}

// ============================================================================
// Position Management Tests (7 scenarios)
// ============================================================================

#[tokio::test]
async fn test_get_positions_empty() {
    let engine = create_test_engine();

    let positions = engine.get_positions(None).await;
    assert!(positions.is_ok());
    assert!(positions.unwrap().is_empty());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_get_positions_after_execution() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(2),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = create_execution(order_id, "BTCUSD", 2, 50000);
    engine.process_execution(execution).await.unwrap();

    let positions = engine.get_positions(None).await.unwrap();
    assert_eq!(positions.len(), 1);
    assert_eq!(positions[0].symbol.to_string(), "BTCUSD");
    assert_eq!(positions[0].quantity, Decimal::from(2));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_get_positions_multiple_symbols() {
    let engine = create_test_engine();

    // BTC position
    let btc_order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let btc_execution = create_execution(btc_order_id, "BTCUSD", 1, 50000);
    engine.process_execution(btc_execution).await.unwrap();

    // ETH position
    let eth_order_id: OrderId = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let eth_execution = create_execution(eth_order_id, "ETHUSD", 10, 3000);
    engine.process_execution(eth_execution).await.unwrap();

    let positions = engine.get_positions(None).await.unwrap();
    assert_eq!(positions.len(), 2);

    let symbols: Vec<String> = positions.iter().map(|p| p.symbol.to_string()).collect();
    assert!(symbols.contains(&"BTCUSD".to_string()));
    assert!(symbols.contains(&"ETHUSD".to_string()));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_get_positions_filtered_by_symbol() {
    let engine = create_test_engine();

    // Create multiple positions
    let btc_order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let btc_execution = create_execution(btc_order_id, "BTCUSD", 1, 50000);
    engine.process_execution(btc_execution).await.unwrap();

    let eth_order_id: OrderId = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let eth_execution = create_execution(eth_order_id, "ETHUSD", 10, 3000);
    engine.process_execution(eth_execution).await.unwrap();

    // Filter for BTC only
    let btc_positions = engine
        .get_positions(Some("BTCUSD".to_string()))
        .await
        .unwrap();

    assert_eq!(btc_positions.len(), 1);
    assert_eq!(btc_positions[0].symbol.to_string(), "BTCUSD");
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_position_increases_with_additional_buy() {
    let engine = create_test_engine();

    // First buy
    let order1_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution1 = create_execution(order1_id, "BTCUSD", 1, 50000);
    engine.process_execution(execution1).await.unwrap();

    // Second buy
    let order2_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution2 = create_execution(order2_id, "BTCUSD", 1, 51000);
    engine.process_execution(execution2).await.unwrap();

    let positions = engine
        .get_positions(Some("BTCUSD".to_string()))
        .await
        .unwrap();

    assert_eq!(positions.len(), 1);
    assert_eq!(positions[0].quantity, Decimal::from(2));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_position_reduces_with_sell() {
    let engine = create_test_engine();

    // Buy 10
    let buy_order_id: OrderId = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let buy_execution = create_execution(buy_order_id, "ETHUSD", 10, 3000);
    engine.process_execution(buy_execution).await.unwrap();

    // Sell 6
    let sell_order_id: OrderId = engine
        .submit_order(
            "ETHUSD".to_string(),
            OrderSide::Sell,
            OrderType::Market,
            Decimal::from(6),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let sell_execution = ExecutionResult {
        order_id: sell_order_id,
        symbol: "ETHUSD".to_string(),
        side: OrderSide::Sell,
        executed_quantity: Decimal::from(6),
        execution_price: Decimal::from(3100),
        execution_time: Utc::now(),
        commission: Decimal::from(10),
        liquidity_flag: LiquidityFlag::Taker,
    };

    engine.process_execution(sell_execution).await.unwrap();

    let positions = engine
        .get_positions(Some("ETHUSD".to_string()))
        .await
        .unwrap();

    assert_eq!(positions.len(), 1);
    assert_eq!(positions[0].quantity, Decimal::from(4));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_position_flattened_with_equal_sell() {
    let engine = create_test_engine();

    // Buy 10
    let buy_order_id: OrderId = engine
        .submit_order(
            "SOLUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let buy_execution = create_execution(buy_order_id, "SOLUSD", 10, 100);
    engine.process_execution(buy_execution).await.unwrap();

    // Sell 10 (flatten)
    let sell_order_id: OrderId = engine
        .submit_order(
            "SOLUSD".to_string(),
            OrderSide::Sell,
            OrderType::Market,
            Decimal::from(10),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let sell_execution = ExecutionResult {
        order_id: sell_order_id,
        symbol: "SOLUSD".to_string(),
        side: OrderSide::Sell,
        executed_quantity: Decimal::from(10),
        execution_price: Decimal::from(110),
        execution_time: Utc::now(),
        commission: Decimal::from(5),
        liquidity_flag: LiquidityFlag::Maker,
    };

    engine.process_execution(sell_execution).await.unwrap();

    let positions = engine
        .get_positions(Some("SOLUSD".to_string()))
        .await
        .unwrap();

    assert_eq!(positions.len(), 1);
    assert_eq!(positions[0].quantity, Decimal::ZERO);
}

// ============================================================================
// Market Data Subscription Tests (3 scenarios)
// ============================================================================

#[tokio::test]
async fn test_subscribe_market_data() {
    let engine = create_test_engine();

    let result = engine
        .subscribe_market_data(vec!["BTCUSD".to_string(), "ETHUSD".to_string()])
        .await;

    assert!(result.is_ok());
}

#[tokio::test]
async fn test_subscribe_order_updates() {
    let engine = create_test_engine();

    let result = engine.subscribe_order_updates(None).await;
    assert!(result.is_ok());
}

#[tokio::test]
async fn test_subscribe_order_updates_with_account() {
    let engine = create_test_engine();

    let result = engine
        .subscribe_order_updates(Some("DEMO_ACCOUNT".to_string()))
        .await;

    assert!(result.is_ok());
}

// ============================================================================
// Trading Stats Tests (2 scenarios)
// ============================================================================

#[tokio::test]
async fn test_get_trading_stats_initial() {
    let engine = create_test_engine();

    let stats = engine.get_trading_stats().await;

    // Initial stats should have zeros
    assert_eq!(stats.total_orders, 0);
    assert_eq!(stats.filled_orders, 0);
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_get_trading_stats_after_orders() {
    let engine = create_test_engine();

    // Submit and execute an order
    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::from(1),
            None,
            None,
        )
        .await
        .unwrap()
        .into();

    let execution = create_execution(order_id, "BTCUSD", 1, 50000);
    engine.process_execution(execution).await.unwrap();

    let stats = engine.get_trading_stats().await;

    assert_eq!(stats.total_orders, 1);
    assert_eq!(stats.filled_orders, 1);
}

// ============================================================================
// Account Info Tests (2 scenarios)
// ============================================================================

#[tokio::test]
async fn test_get_account_info_demo_account() {
    let engine = create_test_engine();

    let account = engine
        .get_account_info("DEMO_ACCOUNT".to_string())
        .await;

    assert!(account.is_ok());

    let account_info = account.unwrap();
    assert_eq!(account_info.account_id, "DEMO_ACCOUNT");
    assert_eq!(account_info.total_value, Decimal::from(100000));
    assert_eq!(account_info.cash_balance, Decimal::from(50000));
}

#[tokio::test]
async fn test_get_account_info_nonexistent() {
    let engine = create_test_engine();

    let result = engine
        .get_account_info("NONEXISTENT".to_string())
        .await;

    assert!(result.is_err());
    assert!(result.unwrap_err().contains("not found"));
}

// ============================================================================
// Edge Cases & Error Handling (5 scenarios)
// ============================================================================

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_concurrent_order_submissions() {
    let engine = Arc::new(create_test_engine());

    let mut handles = vec![];

    for i in 0..5 {
        let engine_clone = Arc::clone(&engine);
        let handle = tokio::spawn(async move {
            engine_clone
                .submit_order(
                    format!("SYM{}", i),
                    OrderSide::Buy,
                    OrderType::Market,
                    Decimal::from(1),
                    None,
                    None,
                )
                .await
        });
        handles.push(handle);
    }

    let results: Vec<_> = futures::future::join_all(handles).await;

    // All should succeed
    for result in results {
        assert!(result.unwrap().is_ok());
    }
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_rapid_fire_executions() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(100),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // Process 10 small executions rapidly
    for i in 1..=10 {
        let execution = create_execution(order_id, "BTCUSD", 10, 50000 + i * 10);
        engine.process_execution(execution).await.unwrap();
    }

    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.status, OrderStatus::Filled);
    assert_eq!(order.fill_quantity, Decimal::from(100));
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_order_after_partial_cancel() {
    let engine = create_test_engine();

    let order_id: OrderId = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(10),
            Some(Decimal::from(50000)),
            None,
        )
        .await
        .unwrap()
        .into();

    // Partial fill
    let execution = create_execution(order_id, "BTCUSD", 3, 50000);
    engine.process_execution(execution).await.unwrap();

    // Cancel the rest
    engine.cancel_order(order_id).await.unwrap();

    let order = engine.get_order_status(order_id).await.unwrap();
    assert_eq!(order.status, OrderStatus::Cancelled);
    assert_eq!(order.fill_quantity, Decimal::from(3)); // Partial fill remains
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_large_order_quantity() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Limit,
            Decimal::from(1000000),
            Some(Decimal::from(1)), // Low price to pass buying power check
            None,
        )
        .await;

    assert!(result.is_ok());
}

#[tokio::test]
#[ignore] // Requires configured broker
async fn test_fractional_order_quantity() {
    let engine = create_test_engine();

    let result = engine
        .submit_order(
            "BTCUSD".to_string(),
            OrderSide::Buy,
            OrderType::Market,
            Decimal::new(15, 1), // 1.5
            None,
            None,
        )
        .await;

    assert!(result.is_ok());
}
