#![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,
)]
//! Comprehensive edge case tests for trading engine managers
//!
//! This test suite covers error paths, boundary conditions, and edge cases
//! to improve overall test coverage toward 95%.

use chrono::{Duration, Utc};
use common::{OrderId, OrderSide, OrderStatus, OrderType, TimeInForce};
use rust_decimal::Decimal;
use std::collections::HashMap;
use trading_engine::trading::{
    account_manager::AccountManager, engine::AccountInfo, order_manager::OrderManager,
    position_manager::PositionManager,
};
use trading_engine::trading_operations::{ExecutionResult, LiquidityFlag, TradingOrder};

// ============================================================================
// Order Manager Edge Cases
// ============================================================================

#[tokio::test]
async fn test_order_manager_zero_price_limit_order() {
    let manager = OrderManager::new();

    let mut order = create_test_order("zero-price", "BTCUSD", 100, 0);
    order.order_type = OrderType::Limit;
    order.price = Decimal::ZERO;

    let result = manager.validate_order(&order).await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("price"));
}

#[tokio::test]
async fn test_order_manager_market_order_with_zero_price() {
    let manager = OrderManager::new();

    let mut order = create_test_order("market-zero", "BTCUSD", 100, 0);
    order.order_type = OrderType::Market;
    order.price = Decimal::ZERO; // Market orders can have zero price

    let result = manager.validate_order(&order).await;
    assert!(result.is_ok());
}

#[tokio::test]
async fn test_order_manager_execution_overfill() {
    let manager = OrderManager::new();

    let mut order = create_test_order("overfill", "BTCUSD", 100, 50000);
    order.status = OrderStatus::Submitted;
    manager.add_order(order.clone()).await;

    // Execute more than ordered quantity
    let execution = ExecutionResult {
        order_id: order.id,
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Buy,
        executed_quantity: Decimal::from(150), // More than 100 ordered
        execution_price: Decimal::from(50000),
        execution_time: Utc::now(),
        commission: Decimal::from(10),
        liquidity_flag: LiquidityFlag::Maker,
    };

    let result = manager.process_execution(&execution).await;
    assert!(result.is_ok());

    let updated = manager.get_order(&order.id).await.unwrap();
    assert_eq!(updated.status, OrderStatus::Filled);
    assert_eq!(updated.fill_quantity, Decimal::from(150));
}

#[tokio::test]
async fn test_order_manager_multiple_partial_fills() {
    let manager = OrderManager::new();

    let mut order = create_test_order("multi-partial", "BTCUSD", 1000, 50000);
    order.status = OrderStatus::Submitted;
    manager.add_order(order.clone()).await;

    // Five partial fills at different prices
    let fills = vec![
        (100, 50000),
        (200, 50010),
        (150, 49990),
        (300, 50020),
        (250, 50005),
    ];

    for (qty, price) in fills {
        let execution = ExecutionResult {
            order_id: order.id,
            symbol: "BTCUSD".to_string(),
            side: OrderSide::Buy,
            executed_quantity: Decimal::from(qty),
            execution_price: Decimal::from(price),
            execution_time: Utc::now(),
            commission: Decimal::from(5),
            liquidity_flag: LiquidityFlag::Maker,
        };

        manager.process_execution(&execution).await.unwrap();
    }

    let updated = manager.get_order(&order.id).await.unwrap();
    assert_eq!(updated.status, OrderStatus::Filled);
    assert_eq!(updated.fill_quantity, Decimal::from(1000));

    // Verify average price is weighted correctly
    // (100*50000 + 200*50010 + 150*49990 + 300*50020 + 250*50005) / 1000
    let expected_avg = Decimal::from(50009);
    assert_eq!(updated.average_fill_price, Some(expected_avg));
}

#[tokio::test]
async fn test_order_manager_cleanup_boundary() {
    let manager = OrderManager::new();

    // Add order exactly at the cutoff time (24 hours ago)
    let mut boundary_order = create_test_order("boundary", "BTCUSD", 100, 50000);
    boundary_order.status = OrderStatus::Filled;
    boundary_order.created_at = Utc::now() - Duration::hours(24);
    let boundary_id = boundary_order.id;
    manager.add_order(boundary_order).await;

    // Cleanup with 24 hour window
    manager.cleanup_old_orders(24).await;

    // Order should be kept (created_at > cutoff_time means keep)
    assert!(manager.get_order(&boundary_id).await.is_some());
}

#[tokio::test]
async fn test_order_manager_get_orders_with_filter() {
    let manager = OrderManager::new();

    let statuses = vec![
        OrderStatus::Created,
        OrderStatus::Submitted,
        OrderStatus::PartiallyFilled,
        OrderStatus::Filled,
        OrderStatus::Cancelled,
        OrderStatus::Rejected,
    ];

    for (i, status) in statuses.iter().enumerate() {
        let mut order = create_test_order(&format!("filter-{}", i), "BTCUSD", 100, 50000);
        order.status = status.clone();
        manager.add_order(order).await;
    }

    // Test filtering by each status
    for status in &statuses {
        let filtered = manager.get_orders(Some(status.clone())).await;
        assert_eq!(filtered.len(), 1);
        assert_eq!(filtered[0].status, *status);
    }

    // Test no filter returns all
    let all_orders = manager.get_orders(None).await;
    assert_eq!(all_orders.len(), 6);
}

// ============================================================================
// Position Manager Edge Cases
// ============================================================================

#[tokio::test]
async fn test_position_manager_flip_from_long_to_short() {
    let manager = PositionManager::new();

    // Open long position
    let buy_exec = ExecutionResult {
        order_id: OrderId::new(),
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Buy,
        executed_quantity: Decimal::from(100),
        execution_price: Decimal::from(50000),
        execution_time: Utc::now(),
        commission: Decimal::from(10),
        liquidity_flag: LiquidityFlag::Maker,
    };

    manager.update_position(&buy_exec).unwrap();

    // Sell more than position (flip to short)
    let sell_exec = ExecutionResult {
        order_id: OrderId::new(),
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Sell,
        executed_quantity: Decimal::from(150),
        execution_price: Decimal::from(51000),
        execution_time: Utc::now(),
        commission: Decimal::from(15),
        liquidity_flag: LiquidityFlag::Taker,
    };

    manager.update_position(&sell_exec).unwrap();

    let position = manager.get_position("BTCUSD").unwrap();
    assert_eq!(position.quantity, Decimal::from(-50)); // Net short 50
    assert_eq!(position.avg_cost, Decimal::from(51000)); // New cost basis at flip price

    // Check realized P&L from closing long position
    // 100 shares * (51000 - 50000) = 100,000
    assert_eq!(position.realized_pnl, Decimal::from(100000));
}

#[tokio::test]
async fn test_position_manager_flip_from_short_to_long() {
    let manager = PositionManager::new();

    // Open short position
    let sell_exec = ExecutionResult {
        order_id: OrderId::new(),
        symbol: "ETHUSD".to_string(),
        side: OrderSide::Sell,
        executed_quantity: Decimal::from(100),
        execution_price: Decimal::from(3000),
        execution_time: Utc::now(),
        commission: Decimal::from(10),
        liquidity_flag: LiquidityFlag::Maker,
    };

    manager.update_position(&sell_exec).unwrap();

    // Buy more than short position (flip to long)
    let buy_exec = ExecutionResult {
        order_id: OrderId::new(),
        symbol: "ETHUSD".to_string(),
        side: OrderSide::Buy,
        executed_quantity: Decimal::from(150),
        execution_price: Decimal::from(2950),
        execution_time: Utc::now(),
        commission: Decimal::from(15),
        liquidity_flag: LiquidityFlag::Taker,
    };

    manager.update_position(&buy_exec).unwrap();

    let position = manager.get_position("ETHUSD").unwrap();
    assert_eq!(position.quantity, Decimal::from(50)); // Net long 50
    assert_eq!(position.avg_cost, Decimal::from(2950)); // New cost basis

    // Check realized P&L from closing short
    // 100 shares * (3000 - 2950) = 5,000 profit
    assert_eq!(position.realized_pnl, Decimal::from(5000));
}

#[tokio::test]
async fn test_position_manager_close_nonexistent_position() {
    let manager = PositionManager::new();

    let result = manager.close_position("NONEXISTENT");
    assert!(result.is_ok());
    assert!(result.unwrap().is_none());
}

#[tokio::test]
async fn test_position_manager_concentration_risk_empty() {
    let manager = PositionManager::new();

    let risk = manager.calculate_concentration_risk();
    assert!(risk.is_empty());
}

#[tokio::test]
async fn test_position_manager_concentration_risk_calculation() {
    let manager = PositionManager::new();

    // Add three positions with different values
    let symbols = vec![
        ("BTCUSD", 100, 50000), // $5M
        ("ETHUSD", 1000, 3000), // $3M
        ("SOLUSD", 10000, 200), // $2M
    ];

    for (symbol, qty, price) in symbols {
        let exec = ExecutionResult {
            order_id: OrderId::new(),
            symbol: symbol.to_string(),
            side: OrderSide::Buy,
            executed_quantity: Decimal::from(qty),
            execution_price: Decimal::from(price),
            execution_time: Utc::now(),
            commission: Decimal::ZERO,
            liquidity_flag: LiquidityFlag::Maker,
        };
        manager.update_position(&exec).unwrap();

        // Update market values
        manager
            .update_market_values(symbol, Decimal::from(price))
            .unwrap();
    }

    let risk = manager.calculate_concentration_risk();

    // Total portfolio = $10M
    // BTCUSD: 50% concentration
    // ETHUSD: 30% concentration
    // SOLUSD: 20% concentration
    assert_eq!(risk.len(), 3);
    assert!((risk["BTCUSD"] - 0.5).abs() < 0.01);
    assert!((risk["ETHUSD"] - 0.3).abs() < 0.01);
    assert!((risk["SOLUSD"] - 0.2).abs() < 0.01);
}

#[tokio::test]
async fn test_position_manager_update_market_values_nonexistent() {
    let manager = PositionManager::new();

    let result = manager.update_market_values("NONEXISTENT", Decimal::from(100));
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("not found"));
}

// ============================================================================
// Account Manager Edge Cases
// ============================================================================

#[tokio::test]
async fn test_account_manager_nonexistent_account() {
    let manager = AccountManager::new();

    let result = manager.get_account_info("NONEXISTENT").await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("not found"));
}

#[tokio::test]
async fn test_account_manager_insufficient_buying_power() {
    let manager = AccountManager::new();

    // Create order that exceeds buying power
    let order = TradingOrder {
        id: OrderId::new(),
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Buy,
        order_type: OrderType::Limit,
        quantity: Decimal::from(10),  // 10 BTC
        price: Decimal::from(100000), // at $100k each = $1M total
        time_in_force: TimeInForce::Day,
        account_id: None,
        metadata: HashMap::new(),
        created_at: Utc::now(),
        submitted_at: None,
        executed_at: None,
        status: OrderStatus::Created,
        fill_quantity: Decimal::ZERO,
        average_fill_price: None,
    };

    let result = manager.check_buying_power(&order).await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("Insufficient buying power"));
}

#[tokio::test]
async fn test_account_manager_sell_order_no_buying_power_check() {
    let manager = AccountManager::new();

    // Sell orders shouldn't require buying power check (for long positions)
    let order = TradingOrder {
        id: OrderId::new(),
        symbol: "BTCUSD".to_string(),
        side: OrderSide::Sell,
        order_type: OrderType::Limit,
        quantity: Decimal::from(100),
        price: Decimal::from(100000),
        time_in_force: TimeInForce::Day,
        account_id: None,
        metadata: HashMap::new(),
        created_at: Utc::now(),
        submitted_at: None,
        executed_at: None,
        status: OrderStatus::Created,
        fill_quantity: Decimal::ZERO,
        average_fill_price: None,
    };

    let result = manager.check_buying_power(&order).await;
    assert!(result.is_ok()); // Sell orders pass
}

#[tokio::test]
async fn test_account_manager_update_from_execution_buy() {
    let manager = AccountManager::new();

    let execution = ExecutionResult {
        order_id: OrderId::new(),
        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),
        liquidity_flag: LiquidityFlag::Maker,
    };

    let result = manager.update_from_execution(&execution).await;
    assert!(result.is_ok());

    let account = manager.get_account_info("DEMO_ACCOUNT").await.unwrap();

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

#[tokio::test]
async fn test_account_manager_margin_call_check() {
    let manager = AccountManager::new();

    // Get current account
    let mut account = manager.get_account_info("DEMO_ACCOUNT").await.unwrap();

    // Set up account with margin call condition
    account.total_value = Decimal::from(80000);
    account.maintenance_margin = Decimal::from(100000); // Margin > value

    manager.update_account_info(account).await.unwrap();

    let is_margin_call = manager.check_margin_call("DEMO_ACCOUNT").await.unwrap();
    assert!(is_margin_call);
}

#[tokio::test]
async fn test_account_manager_no_margin_call() {
    let manager = AccountManager::new();

    // Default demo account has no margin requirement
    let is_margin_call = manager.check_margin_call("DEMO_ACCOUNT").await.unwrap();
    assert!(!is_margin_call);
}

#[tokio::test]
async fn test_account_manager_add_duplicate_account() {
    let manager = AccountManager::new();

    let account = AccountInfo {
        account_id: "TEST_ACCOUNT".to_string(),
        total_value: Decimal::from(50000),
        cash_balance: Decimal::from(50000),
        buying_power: Decimal::from(50000),
        maintenance_margin: Decimal::ZERO,
        day_trading_buying_power: Decimal::from(100000),
    };

    // Add once
    let result1 = manager.add_account(account.clone()).await;
    assert!(result1.is_ok());

    // Try to add same account again
    let result2 = manager.add_account(account).await;
    assert!(result2.is_err());
    assert!(result2.unwrap_err().contains("already exists"));
}

#[tokio::test]
async fn test_account_manager_remove_nonexistent_account() {
    let manager = AccountManager::new();

    let result = manager.remove_account("NONEXISTENT").await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("not found"));
}

#[tokio::test]
async fn test_account_manager_remove_demo_account_protected() {
    let manager = AccountManager::new();

    // Demo account should be protected from deletion
    let result = manager.remove_account("DEMO_ACCOUNT").await;
    assert!(result.is_err());
    assert!(result.unwrap_err().contains("Cannot remove"));
}

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

fn create_test_order(id: &str, symbol: &str, quantity: i64, price: i64) -> TradingOrder {
    TradingOrder {
        id: id.to_string().into(),
        symbol: symbol.to_string(),
        side: OrderSide::Buy,
        order_type: OrderType::Limit,
        quantity: Decimal::from(quantity),
        price: Decimal::from(price),
        time_in_force: TimeInForce::GoodTillCancel,
        account_id: None,
        metadata: HashMap::new(),
        created_at: Utc::now(),
        submitted_at: None,
        executed_at: None,
        status: OrderStatus::Created,
        fill_quantity: Decimal::ZERO,
        average_fill_price: None,
    }
}
