#![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 brokers module tests targeting 95% coverage
//! Tests for brokers/mod.rs and related broker connection functionality
//!
//! These tests exercise BrokerConnector with default configuration, where no
//! broker clients are actually connected. submit_order/cancel_order correctly
//! return Err when no broker is available, and get_connected_brokers returns
//! an empty list.

use chrono::Utc;
use common::{OrderSide, OrderStatus, OrderType, TimeInForce};
use rust_decimal::Decimal;
use std::collections::HashMap;
use trading_engine::brokers::config::BrokerConnectorConfig;
use trading_engine::brokers::BrokerConnector;
use trading_engine::trading_operations::TradingOrder;

/// Create a minimal TradingOrder for testing.
fn make_test_order(symbol: &str) -> TradingOrder {
    TradingOrder {
        id: common::OrderId::new(),
        symbol: symbol.to_owned(),
        side: OrderSide::Buy,
        order_type: OrderType::Market,
        quantity: Decimal::from(1),
        price: Decimal::from(100),
        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,
    }
}

// ============================================================================
// BrokerConnector::new() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_creation_tests {
    use super::*;

    #[test]
    fn test_broker_connector_new_default_config() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);
        // Verify connector was created (should not panic)
        assert!(format!("{:?}", connector).contains("BrokerConnector"));
    }

    #[test]
    fn test_broker_connector_new_custom_config() {
        let mut config = BrokerConnectorConfig::default();
        config.brokers.interactive_brokers.enabled = true;
        config.fail_on_broker_error = true;

        let connector = BrokerConnector::new(config);
        assert!(format!("{:?}", connector).contains("BrokerConnector"));
    }

    #[test]
    fn test_broker_connector_new_disabled_config() {
        let mut config = BrokerConnectorConfig::default();
        config.brokers.interactive_brokers.enabled = false;

        let connector = BrokerConnector::new(config);
        assert!(format!("{:?}", connector).contains("BrokerConnector"));
    }

    #[test]
    fn test_multiple_broker_connectors_independent() {
        let config1 = BrokerConnectorConfig::default();
        let config2 = BrokerConnectorConfig::default();

        let connector1 = BrokerConnector::new(config1);
        let connector2 = BrokerConnector::new(config2);

        // Both should be independent instances
        assert!(format!("{:?}", connector1).contains("BrokerConnector"));
        assert!(format!("{:?}", connector2).contains("BrokerConnector"));
    }
}

// ============================================================================
// BrokerConnector::initialize() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_initialization_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_initialize_success() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        let result = connector.initialize().await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_initialize_multiple_times() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        // Initialize multiple times should be safe
        assert!(connector.initialize().await.is_ok());
        assert!(connector.initialize().await.is_ok());
        assert!(connector.initialize().await.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_initialize_with_custom_config() {
        let mut config = BrokerConnectorConfig::default();
        config.fail_on_broker_error = true;

        let mut connector = BrokerConnector::new(config);
        // With default broker configs (both disabled) and fail_on_broker_error=true,
        // initialize succeeds because no connection attempts are made for disabled brokers.
        let result = connector.initialize().await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_initialize_concurrent() {
        let config = BrokerConnectorConfig::default();
        let mut connector1 = BrokerConnector::new(config.clone());
        let mut connector2 = BrokerConnector::new(config);

        let (result1, result2) = tokio::join!(connector1.initialize(), connector2.initialize());

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

// ============================================================================
// BrokerConnector::submit_order() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_submit_order_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_submit_order_no_broker_connected() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let order = make_test_order("ES.FUT");
        let result = connector.submit_order(&order).await;
        // With default config, IB is enabled=false so ib_client is None.
        // submit_order routes to "InteractiveBrokers" and returns an error.
        assert!(result.is_err(), "submit_order should fail when no broker is configured");
    }

    #[tokio::test]
    async fn test_broker_connector_submit_order_multiple() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let result1 = connector.submit_order(&make_test_order("ES.FUT")).await;
        let result2 = connector.submit_order(&make_test_order("NQ.FUT")).await;
        let result3 = connector.submit_order(&make_test_order("6E.FUT")).await;

        // All should return errors (no broker connected)
        assert!(result1.is_err());
        assert!(result2.is_err());
        assert!(result3.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_submit_order_various_symbols() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let symbols = vec!["ES.FUT", "NQ.FUT", "6E.FUT", "ZN.FUT"];

        for symbol in symbols {
            let order = make_test_order(symbol);
            let result = connector.submit_order(&order).await;
            assert!(result.is_err(), "Expected error for symbol: {}", symbol);
        }
    }

    #[tokio::test]
    async fn test_broker_connector_submit_order_concurrent() {
        let config = BrokerConnectorConfig::default();
        let connector = std::sync::Arc::new(BrokerConnector::new(config));

        let mut handles = vec![];
        for i in 0..10 {
            let connector_clone = connector.clone();
            let handle = tokio::spawn(async move {
                let order = make_test_order(&format!("SYM_{}", i));
                let result = connector_clone.submit_order(&order).await;
                assert!(result.is_err(), "Expected error for concurrent order {}", i);
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.await.expect("Task should not panic");
        }
    }

    #[tokio::test]
    async fn test_broker_connector_submit_order_unknown_broker() {
        let mut config = BrokerConnectorConfig::default();
        config.routing.default_broker = "UnknownBroker".to_owned();
        let connector = BrokerConnector::new(config);

        let order = make_test_order("ES.FUT");
        let result = connector.submit_order(&order).await;
        assert!(result.is_err());
        let err_msg = result.err().map(|e| e.to_string()).unwrap_or_default();
        assert!(
            err_msg.contains("Unknown default broker"),
            "Expected unknown broker error, got: {}",
            err_msg
        );
    }

    #[tokio::test]
    async fn test_broker_connector_submit_order_icmarkets_not_connected() {
        let mut config = BrokerConnectorConfig::default();
        config.routing.default_broker = "ICMarkets".to_owned();
        // ICMarkets is disabled by default so icm_client = None
        let connector = BrokerConnector::new(config);

        let order = make_test_order("EURUSD");
        let result = connector.submit_order(&order).await;
        assert!(result.is_err());
    }
}

// ============================================================================
// BrokerConnector::cancel_order() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_cancel_order_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_cancel_order_no_broker_connected() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let result = connector.cancel_order("ORD_123").await;
        // No brokers connected, so cancel fails
        assert!(result.is_err(), "cancel_order should fail when no broker is connected");
    }

    #[tokio::test]
    async fn test_broker_connector_cancel_order_nonexistent() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let result = connector.cancel_order("NONEXISTENT").await;
        assert!(result.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_cancel_order_multiple_times() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        // Cancel same order multiple times - all should fail (no broker)
        let order_id = "ORD_999";
        assert!(connector.cancel_order(order_id).await.is_err());
        assert!(connector.cancel_order(order_id).await.is_err());
        assert!(connector.cancel_order(order_id).await.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_cancel_order_empty_id() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let result = connector.cancel_order("").await;
        assert!(result.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_cancel_order_concurrent() {
        let config = BrokerConnectorConfig::default();
        let connector = std::sync::Arc::new(BrokerConnector::new(config));

        let mut handles = vec![];
        for i in 0..10 {
            let connector_clone = connector.clone();
            let handle = tokio::spawn(async move {
                let result = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
                assert!(result.is_err(), "Expected error for concurrent cancel {}", i);
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.await.expect("Task should not panic");
        }
    }

    #[tokio::test]
    async fn test_broker_connector_submit_and_cancel_workflow() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        // Both submit and cancel should return errors (no broker connected)
        let order = make_test_order("ES.FUT");
        let submit_result = connector.submit_order(&order).await;
        assert!(submit_result.is_err());

        let cancel_result = connector.cancel_order("ORD_WORKFLOW").await;
        assert!(cancel_result.is_err());
    }
}

// ============================================================================
// BrokerConnector::get_connected_brokers() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_get_connected_brokers_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_get_connected_brokers_initial() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let brokers = connector.get_connected_brokers().await;
        // Default config: both brokers disabled, none connected
        assert!(
            brokers.is_empty(),
            "Expected no connected brokers with default config, got: {:?}",
            brokers
        );
    }

    #[tokio::test]
    async fn test_broker_connector_get_connected_brokers_after_init() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        connector.initialize().await.expect("init should succeed");

        let brokers = connector.get_connected_brokers().await;
        // Still empty because no broker is enabled in default config
        assert!(brokers.is_empty());
    }

    #[tokio::test]
    async fn test_broker_connector_get_connected_brokers_multiple_calls() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let brokers1 = connector.get_connected_brokers().await;
        let brokers2 = connector.get_connected_brokers().await;
        let brokers3 = connector.get_connected_brokers().await;

        assert_eq!(brokers1, brokers2);
        assert_eq!(brokers2, brokers3);
    }

    #[tokio::test]
    async fn test_broker_connector_get_connected_brokers_concurrent() {
        let config = BrokerConnectorConfig::default();
        let connector = std::sync::Arc::new(BrokerConnector::new(config));

        let mut handles = vec![];
        for _ in 0..5 {
            let connector_clone = connector.clone();
            let handle = tokio::spawn(async move { connector_clone.get_connected_brokers().await });
            handles.push(handle);
        }

        for handle in handles {
            let brokers = handle.await.expect("Task should not panic");
            assert!(brokers.is_empty());
        }
    }
}

// ============================================================================
// BrokerConnector::shutdown() Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_shutdown_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_shutdown_success() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        connector.initialize().await.expect("init should succeed");

        let result = connector.shutdown().await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_shutdown_without_init() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        let result = connector.shutdown().await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_shutdown_multiple_times() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        connector.initialize().await.expect("init should succeed");

        assert!(connector.shutdown().await.is_ok());
        assert!(connector.shutdown().await.is_ok());
        assert!(connector.shutdown().await.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_init_shutdown_cycle() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        // Multiple init-shutdown cycles
        for _ in 0..3 {
            assert!(connector.initialize().await.is_ok());
            assert!(connector.shutdown().await.is_ok());
        }
    }
}

// ============================================================================
// BrokerConfig Tests
// ============================================================================

#[cfg(test)]
mod broker_config_tests {
    use super::*;

    #[test]
    fn test_broker_config_default() {
        let config = BrokerConnectorConfig::default();
        assert!(format!("{:?}", config).contains("BrokerConnectorConfig"));
    }

    #[test]
    fn test_broker_config_enabled_flag() {
        let mut config = BrokerConnectorConfig::default();

        config.brokers.interactive_brokers.enabled = true;
        assert!(config.brokers.interactive_brokers.enabled);

        config.brokers.interactive_brokers.enabled = false;
        assert!(!config.brokers.interactive_brokers.enabled);
    }

    #[test]
    fn test_broker_config_fail_on_broker_error_flag() {
        let mut config = BrokerConnectorConfig::default();

        config.fail_on_broker_error = true;
        assert!(config.fail_on_broker_error);

        config.fail_on_broker_error = false;
        assert!(!config.fail_on_broker_error);
    }

    #[test]
    fn test_broker_config_clone() {
        let config1 = BrokerConnectorConfig::default();
        let config2 = config1.clone();

        assert_eq!(
            config1.brokers.interactive_brokers.enabled,
            config2.brokers.interactive_brokers.enabled
        );
        assert_eq!(config1.fail_on_broker_error, config2.fail_on_broker_error);
    }
}

// ============================================================================
// Integration and Workflow Tests
// ============================================================================

#[cfg(test)]
mod broker_connector_integration_tests {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_complete_workflow() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        // Initialize
        assert!(connector.initialize().await.is_ok());

        // Get connected brokers (empty -- no broker enabled by default)
        let brokers = connector.get_connected_brokers().await;
        assert!(brokers.is_empty());

        // Submit orders (should fail -- no broker connected)
        let order1 = make_test_order("ES.FUT");
        let order2 = make_test_order("NQ.FUT");
        assert!(connector.submit_order(&order1).await.is_err());
        assert!(connector.submit_order(&order2).await.is_err());

        // Cancel orders (should fail -- no broker connected)
        assert!(connector.cancel_order("ORD_001").await.is_err());
        assert!(connector.cancel_order("ORD_002").await.is_err());

        // Shutdown
        assert!(connector.shutdown().await.is_ok());
    }

    #[tokio::test]
    async fn test_broker_connector_high_volume_orders() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        connector.initialize().await.expect("init should succeed");

        // Submit 100 orders (all should fail -- no broker connected)
        for i in 0..100 {
            let order = make_test_order(&format!("SYM_{:04}", i));
            let result = connector.submit_order(&order).await;
            assert!(result.is_err());
        }

        connector.shutdown().await.expect("shutdown should succeed");
    }

    #[tokio::test]
    async fn test_broker_connector_concurrent_operations() {
        let config = BrokerConnectorConfig::default();
        let connector = std::sync::Arc::new(BrokerConnector::new(config));

        let submit_handles: Vec<_> = (0..10)
            .map(|i| {
                let connector_clone = connector.clone();
                tokio::spawn(async move {
                    let order = make_test_order(&format!("SYM_{}", i));
                    let _ = connector_clone.submit_order(&order).await;
                })
            })
            .collect();

        let cancel_handles: Vec<_> = (0..10)
            .map(|i| {
                let connector_clone = connector.clone();
                tokio::spawn(async move {
                    let _ = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
                })
            })
            .collect();

        let broker_handles: Vec<_> = (0..5)
            .map(|_| {
                let connector_clone = connector.clone();
                tokio::spawn(async move { connector_clone.get_connected_brokers().await })
            })
            .collect();

        // All operations should complete without panicking
        for handle in submit_handles {
            handle.await.expect("submit task should not panic");
        }
        for handle in cancel_handles {
            handle.await.expect("cancel task should not panic");
        }
        for handle in broker_handles {
            let brokers = handle.await.expect("broker list task should not panic");
            assert!(brokers.is_empty());
        }
    }

    #[tokio::test]
    async fn test_broker_connector_stress_test() {
        let config = BrokerConnectorConfig::default();
        let connector = std::sync::Arc::new(BrokerConnector::new(config));

        // Simulate high concurrent load
        let mut handles = vec![];
        for i in 0..50 {
            let connector_clone = connector.clone();
            let handle = tokio::spawn(async move {
                match i % 3 {
                    0 => {
                        let order = make_test_order(&format!("SYM_{}", i));
                        let _ = connector_clone.submit_order(&order).await;
                    }
                    1 => {
                        let _ = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
                    }
                    _ => {
                        connector_clone.get_connected_brokers().await;
                    }
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.await.expect("stress test task should not panic");
        }
    }
}

// ============================================================================
// Edge Cases and Error Conditions
// ============================================================================

#[cfg(test)]
mod broker_connector_edge_cases {
    use super::*;

    #[tokio::test]
    async fn test_broker_connector_operations_before_init() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        // Operations should return errors (no broker connected) even without init
        let order = make_test_order("ES.FUT");
        assert!(connector.submit_order(&order).await.is_err());
        assert!(connector.cancel_order("ORD_123").await.is_err());
        assert!(connector.get_connected_brokers().await.is_empty());
    }

    #[tokio::test]
    async fn test_broker_connector_operations_after_shutdown() {
        let config = BrokerConnectorConfig::default();
        let mut connector = BrokerConnector::new(config);

        connector.initialize().await.expect("init should succeed");
        connector.shutdown().await.expect("shutdown should succeed");

        // Operations should return errors after shutdown
        let order = make_test_order("ES.FUT");
        assert!(connector.submit_order(&order).await.is_err());
        assert!(connector.cancel_order("ORD_123").await.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_different_order_sides() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let mut buy_order = make_test_order("ES.FUT");
        buy_order.side = OrderSide::Buy;
        assert!(connector.submit_order(&buy_order).await.is_err());

        let mut sell_order = make_test_order("ES.FUT");
        sell_order.side = OrderSide::Sell;
        assert!(connector.submit_order(&sell_order).await.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_different_order_types() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let mut market_order = make_test_order("ES.FUT");
        market_order.order_type = OrderType::Market;
        assert!(connector.submit_order(&market_order).await.is_err());

        let mut limit_order = make_test_order("ES.FUT");
        limit_order.order_type = OrderType::Limit;
        limit_order.price = Decimal::from(5000);
        assert!(connector.submit_order(&limit_order).await.is_err());
    }

    #[tokio::test]
    async fn test_broker_connector_order_with_metadata() {
        let config = BrokerConnectorConfig::default();
        let connector = BrokerConnector::new(config);

        let mut order = make_test_order("ES.FUT");
        order.metadata.insert("strategy".to_owned(), "mean_reversion".to_owned());
        order.metadata.insert("signal_strength".to_owned(), "0.85".to_owned());
        assert!(connector.submit_order(&order).await.is_err());
    }
}
