//! Comprehensive tests for config/src/structures.rs
//!
//! This test suite validates:
//! - Serialization/deserialization (JSON, YAML)
//! - Default implementations
//! - Trait implementations (Clone, Debug, PartialEq)
//! - Business logic (broker routing, asset classification, commission calculation)
//! - Edge cases and validation

use config::structures::*;
use rust_decimal::Decimal;

// ============================================================================
// SECTION 1: Serialization/Deserialization Tests (6 tests)
// ============================================================================

#[test]
fn test_risk_config_json_serialization() {
    let risk_config = RiskConfig::default();

    // Serialize to JSON
    let json = serde_json::to_string(&risk_config).expect("Failed to serialize RiskConfig");
    assert!(!json.is_empty(), "JSON should not be empty");
    assert!(
        json.contains("max_position_size"),
        "JSON should contain max_position_size field"
    );
    assert!(
        json.contains("var_confidence_level"),
        "JSON should contain var_confidence_level field"
    );

    // Verify key fields are present
    assert!(
        json.contains("circuit_breaker"),
        "JSON should contain nested circuit_breaker"
    );
    assert!(
        json.contains("position_limits"),
        "JSON should contain nested position_limits"
    );
    assert!(
        json.contains("asset_classification"),
        "JSON should contain nested asset_classification"
    );
}

#[test]
fn test_risk_config_json_deserialization() {
    let json = r#"{
        "max_position_size": "500000",
        "max_portfolio_exposure": "5000000",
        "max_concentration_pct": "0.30",
        "max_daily_loss": "75000",
        "max_drawdown_pct": "0.20",
        "stop_loss_threshold": "40000",
        "var_confidence_level": 0.99,
        "var_time_horizon": 5,
        "var_limit_1d": "60000",
        "var_limit_10d": "180000",
        "max_order_size": 150000,
        "max_orders_per_second": 150,
        "max_notional_per_hour": "15000000",
        "kelly_fraction_limit": 0.30,
        "max_kelly_position_size": 0.25,
        "emergency_stop_threshold": 0.12,
        "var_config": {
            "confidence_level": 0.99,
            "time_horizon_days": 5,
            "lookback_period_days": 300,
            "calculation_method": "monte_carlo",
            "max_var_limit": 120000.0
        },
        "circuit_breaker": {
            "enabled": false,
            "price_move_threshold": 0.08,
            "halt_duration_seconds": 600
        },
        "position_limits": {
            "global_limit": 15000000.0,
            "max_leverage": 4.0,
            "max_var_limit": 120000.0
        },
        "asset_classification": {
            "asset_type_rules": {},
            "default_sectors": {},
            "currency_patterns": [],
            "crypto_patterns": []
        }
    }"#;

    let deserialized: RiskConfig =
        serde_json::from_str(json).expect("Failed to deserialize RiskConfig");

    // Verify critical fields
    assert_eq!(deserialized.max_position_size, Decimal::new(500_000, 0));
    assert_eq!(deserialized.var_confidence_level, 0.99);
    assert_eq!(deserialized.max_orders_per_second, 150);
    assert!(
        !deserialized.circuit_breaker.enabled,
        "Circuit breaker should be disabled"
    );
    assert_eq!(deserialized.position_limits.max_leverage, 4.0);
}

#[test]
fn test_var_config_yaml_serialization() {
    let var_config = VarConfig {
        confidence_level: 0.99,
        time_horizon_days: 10,
        lookback_period_days: 500,
        calculation_method: "monte_carlo".to_string(),
        max_var_limit: 250_000.0,
    };

    // Serialize to YAML
    let yaml = serde_yaml::to_string(&var_config).expect("Failed to serialize VarConfig to YAML");
    assert!(!yaml.is_empty(), "YAML should not be empty");
    assert!(
        yaml.contains("confidence_level"),
        "YAML should contain confidence_level"
    );
    assert!(
        yaml.contains("monte_carlo"),
        "YAML should contain calculation_method value"
    );
    assert!(
        yaml.contains("250000"),
        "YAML should contain max_var_limit value"
    );
}

#[test]
fn test_kelly_config_yaml_deserialization() {
    let yaml = r#"
kelly_fraction: 0.35
max_kelly_leverage: 3.0
min_kelly_leverage: 0.2
confidence_threshold: 0.98
lookback_periods: 365
default_position_fraction: 0.03
enabled: false
fractional_kelly: 0.6
min_kelly_fraction: 0.02
max_kelly_fraction: 0.6
"#;

    let deserialized: KellyConfig =
        serde_yaml::from_str(yaml).expect("Failed to deserialize KellyConfig from YAML");

    // Verify all fields
    assert_eq!(deserialized.kelly_fraction, 0.35);
    assert_eq!(deserialized.max_kelly_leverage, 3.0);
    assert_eq!(deserialized.min_kelly_leverage, 0.2);
    assert_eq!(deserialized.confidence_threshold, 0.98);
    assert_eq!(deserialized.lookback_periods, 365);
    assert!(!deserialized.enabled, "Kelly config should be disabled");
}

#[test]
fn test_broker_config_json_roundtrip() {
    let original = BrokerConfig::default();

    // Serialize and deserialize
    let json = serde_json::to_string(&original).expect("Failed to serialize BrokerConfig");
    let deserialized: BrokerConfig =
        serde_json::from_str(&json).expect("Failed to deserialize BrokerConfig");

    // Verify structural integrity
    assert_eq!(original.default_broker, deserialized.default_broker);
    assert_eq!(
        original.routing_rules.len(),
        deserialized.routing_rules.len()
    );
    assert_eq!(
        original.commission_rates.len(),
        deserialized.commission_rates.len()
    );

    // Verify commission rates match
    for (broker, config) in &original.commission_rates {
        let deser_config = deserialized
            .commission_rates
            .get(broker)
            .expect("Broker should exist");
        assert_eq!(config.rate_bps, deser_config.rate_bps);
        assert_eq!(config.min_commission, deser_config.min_commission);
    }
}

#[test]
fn test_asset_classification_config_serde_with_enums() {
    let config = AssetClassificationConfig::default();

    // Serialize to JSON
    let json =
        serde_json::to_string(&config).expect("Failed to serialize AssetClassificationConfig");

    // Verify enum values are properly serialized
    assert!(
        json.contains("Equities") || json.contains("equities"),
        "Should contain Equities asset class"
    );
    assert!(
        json.contains("Alternatives") || json.contains("alternatives"),
        "Should contain Alternatives asset class"
    );

    // Deserialize back
    let deserialized: AssetClassificationConfig =
        serde_json::from_str(&json).expect("Failed to deserialize");

    // Verify symbol mappings match
    assert_eq!(
        config.symbol_mappings.len(),
        deserialized.symbol_mappings.len()
    );
    assert_eq!(
        config.volatility_profiles.len(),
        deserialized.volatility_profiles.len()
    );
}

// ============================================================================
// SECTION 2: Default Implementation Tests (6 tests)
// ============================================================================

#[test]
fn test_risk_config_default_values() {
    let risk_config = RiskConfig::default();

    // Position and exposure limits
    assert_eq!(risk_config.max_position_size, Decimal::new(1_000_000, 0));
    assert_eq!(
        risk_config.max_portfolio_exposure,
        Decimal::new(10_000_000, 0)
    );
    assert_eq!(risk_config.max_concentration_pct, Decimal::new(25_i64, 2));

    // Loss and drawdown limits
    assert_eq!(risk_config.max_daily_loss, Decimal::new(100_000, 0));
    assert_eq!(risk_config.max_drawdown_pct, Decimal::new(15_i64, 2));
    assert_eq!(risk_config.stop_loss_threshold, Decimal::new(50_000, 0));

    // VaR configuration
    assert_eq!(risk_config.var_confidence_level, 0.95);
    assert_eq!(risk_config.var_time_horizon, 1);
    assert_eq!(risk_config.var_limit_1d, Decimal::new(50_000, 0));

    // Kelly criterion
    assert_eq!(risk_config.kelly_fraction_limit, 0.25);
    assert_eq!(risk_config.max_kelly_position_size, 0.20);

    // Nested configs have defaults
    assert!(risk_config.circuit_breaker.enabled);
    assert!(risk_config.var_config.confidence_level > 0.0);
}

#[test]
fn test_var_config_default_values() {
    let var_config = VarConfig::default();

    assert_eq!(var_config.confidence_level, 0.95);
    assert_eq!(var_config.time_horizon_days, 1);
    assert_eq!(var_config.lookback_period_days, 252);
    assert_eq!(var_config.calculation_method, "historical");
    assert_eq!(var_config.max_var_limit, 100_000.0);
}

#[test]
fn test_kelly_config_default_values() {
    let kelly_config = KellyConfig::default();

    assert_eq!(kelly_config.kelly_fraction, 0.25);
    assert_eq!(kelly_config.max_kelly_leverage, 2.0);
    assert_eq!(kelly_config.min_kelly_leverage, 0.1);
    assert_eq!(kelly_config.confidence_threshold, 0.95);
    assert_eq!(kelly_config.lookback_periods, 252);
    assert_eq!(kelly_config.default_position_fraction, 0.02);
    assert!(kelly_config.enabled);
    assert_eq!(kelly_config.fractional_kelly, 0.5);
}

#[test]
fn test_broker_config_default_routing_rules() {
    let broker_config = BrokerConfig::default();

    // Verify default broker
    assert_eq!(broker_config.default_broker, "IBKR");

    // Verify routing rules exist
    assert_eq!(
        broker_config.routing_rules.len(),
        3,
        "Should have 3 default routing rules"
    );

    // Verify crypto rule (highest priority)
    let crypto_rule = &broker_config.routing_rules[0];
    assert_eq!(crypto_rule.priority, 100);
    assert!(
        crypto_rule.symbol_pattern.contains("BTC") || crypto_rule.symbol_pattern.contains("ETH")
    );
    assert_eq!(crypto_rule.broker_id, "ICMARKETS");

    // Verify commission rates exist
    assert!(broker_config.commission_rates.contains_key("ICMARKETS"));
    assert!(broker_config.commission_rates.contains_key("IBKR"));
}

#[test]
fn test_encryption_config_default_secure_settings() {
    let encryption_config = EncryptionConfig::default();

    assert!(
        !encryption_config.enable_encryption,
        "Encryption should be disabled by default"
    );
    assert_eq!(encryption_config.algorithm, "AES-256-GCM");
    assert_eq!(encryption_config.key_rotation_days, 90);
    assert!(
        encryption_config.encryption_keys_vault_path.is_none(),
        "Vault path should be None by default"
    );
    assert!(
        encryption_config.local_key_file.is_none(),
        "Local key file should be None by default"
    );
}

#[test]
fn test_tls_config_default_secure_settings() {
    let tls_config = TlsConfig::default();

    assert!(!tls_config.enabled, "TLS should be disabled by default");
    assert!(
        !tls_config.require_client_cert,
        "Client cert should not be required by default"
    );
    assert_eq!(tls_config.protocol_versions, vec!["TLSv1.3"]);
    assert!(
        tls_config.cipher_suites.is_empty(),
        "Cipher suites should use defaults"
    );

    // Verify paths are set (from env or defaults)
    assert!(!tls_config.cert_path.is_empty());
    assert!(!tls_config.key_path.is_empty());
}

// ============================================================================
// SECTION 3: Clone and Trait Implementation Tests (4 tests)
// ============================================================================

#[test]
fn test_risk_config_clone_independence() {
    let original = RiskConfig::default();
    let mut cloned = original.clone();

    // Modify cloned version
    cloned.max_position_size = Decimal::new(2_000_000, 0);
    cloned.var_confidence_level = 0.99;
    cloned.max_orders_per_second = 200;

    // Verify original is unchanged
    assert_eq!(original.max_position_size, Decimal::new(1_000_000, 0));
    assert_eq!(original.var_confidence_level, 0.95);
    assert_eq!(original.max_orders_per_second, 100);

    // Verify cloned has new values
    assert_eq!(cloned.max_position_size, Decimal::new(2_000_000, 0));
    assert_eq!(cloned.var_confidence_level, 0.99);
    assert_eq!(cloned.max_orders_per_second, 200);
}

#[test]
fn test_asset_class_enum_partialeq() {
    let equities1 = AssetClass::Equities;
    let equities2 = AssetClass::Equities;
    let alternatives = AssetClass::Alternatives;

    // Test equality
    assert_eq!(equities1, equities2);
    assert_ne!(equities1, alternatives);

    // Test all variants
    assert_eq!(AssetClass::Equities, AssetClass::Equities);
    assert_eq!(AssetClass::FixedIncome, AssetClass::FixedIncome);
    assert_eq!(AssetClass::Commodities, AssetClass::Commodities);
    assert_eq!(AssetClass::Currencies, AssetClass::Currencies);
    assert_eq!(AssetClass::Alternatives, AssetClass::Alternatives);
    assert_eq!(AssetClass::Derivatives, AssetClass::Derivatives);
    assert_eq!(AssetClass::Cash, AssetClass::Cash);
}

#[test]
fn test_broker_config_debug_trait() {
    let broker_config = BrokerConfig::default();

    // Test Debug formatting
    let debug_str = format!("{:?}", broker_config);

    assert!(!debug_str.is_empty());
    assert!(debug_str.contains("BrokerConfig"));
    assert!(debug_str.contains("default_broker"));
    assert!(debug_str.contains("routing_rules"));

    // Verify no sensitive data leak (API keys, credentials)
    // (Note: This config doesn't have sensitive fields, but pattern is important)
}

#[test]
fn test_nested_struct_clone_deep_copy() {
    let original = RiskConfig::default();
    let mut cloned = original.clone();

    // Modify nested struct in clone
    cloned.circuit_breaker.price_move_threshold = 0.10;
    cloned.var_config.confidence_level = 0.99;

    // Verify original nested structs unchanged
    assert_eq!(original.circuit_breaker.price_move_threshold, 0.05);
    assert_eq!(original.var_config.confidence_level, 0.95);

    // Verify clone has modified values
    assert_eq!(cloned.circuit_breaker.price_move_threshold, 0.10);
    assert_eq!(cloned.var_config.confidence_level, 0.99);
}

// ============================================================================
// SECTION 4: Business Logic Tests - Broker Selection (5 tests)
// ============================================================================

#[test]
fn test_broker_selection_crypto_routing() {
    let broker_config = BrokerConfig::default();

    // Test BTC/ETH routing to ICMARKETS (priority 100)
    assert_eq!(
        broker_config.select_broker("BTCUSD", 100_000.0),
        "ICMARKETS"
    );
    assert_eq!(broker_config.select_broker("ETHUSD", 50_000.0), "ICMARKETS");
    assert_eq!(
        broker_config.select_broker("btcusdt", 200_000.0),
        "ICMARKETS"
    );
    assert_eq!(
        broker_config.select_broker("ethusdt", 75_000.0),
        "ICMARKETS"
    );
}

#[test]
fn test_broker_selection_usd_pairs_quantity_based() {
    let broker_config = BrokerConfig::default();

    // Test USD pairs with quantity <= 1M route to ICMARKETS (priority 90)
    assert_eq!(
        broker_config.select_broker("EURUSD", 500_000.0),
        "ICMARKETS"
    );
    assert_eq!(
        broker_config.select_broker("GBPUSD", 999_999.0),
        "ICMARKETS"
    );
    assert_eq!(
        broker_config.select_broker("EURUSD", 1_000_000.0),
        "ICMARKETS"
    );

    // Test USD pairs with quantity > 1M don't match USD rule (max_quantity is exclusive)
    // Fall through to catch-all rule (priority 50) which routes to IBKR
    assert_eq!(broker_config.select_broker("EURUSD", 1_000_001.0), "IBKR");
    assert_eq!(broker_config.select_broker("GBPUSD", 2_000_000.0), "IBKR");
}

#[test]
fn test_broker_selection_default_fallback() {
    let broker_config = BrokerConfig::default();

    // Test symbols that don't match specific rules fall back to default
    assert_eq!(broker_config.select_broker("AAPL", 100_000.0), "IBKR");
    assert_eq!(broker_config.select_broker("MSFT", 50_000.0), "IBKR");
    assert_eq!(broker_config.select_broker("TSLA", 200_000.0), "IBKR");
}

#[test]
fn test_broker_selection_priority_ordering() {
    let broker_config = BrokerConfig::default();

    // BTCUSD matches both crypto rule (100) and USD rule (90)
    // Should select higher priority (crypto -> ICMARKETS)
    assert_eq!(
        broker_config.select_broker("BTCUSD", 500_000.0),
        "ICMARKETS"
    );

    // ETHUSD same scenario
    assert_eq!(
        broker_config.select_broker("ETHUSD", 800_000.0),
        "ICMARKETS"
    );
}

#[test]
fn test_broker_selection_case_insensitive() {
    let broker_config = BrokerConfig::default();

    // Test case insensitivity
    assert_eq!(
        broker_config.select_broker("btcusd", 100_000.0),
        "ICMARKETS"
    );
    assert_eq!(
        broker_config.select_broker("BTCUSD", 100_000.0),
        "ICMARKETS"
    );
    assert_eq!(
        broker_config.select_broker("BtCuSd", 100_000.0),
        "ICMARKETS"
    );
}

// ============================================================================
// SECTION 5: Business Logic Tests - Commission Calculation (3 tests)
// ============================================================================

#[test]
fn test_commission_calculation_icmarkets() {
    let broker_config = BrokerConfig::default();

    // ICMarkets: 0.7 bps, no minimum
    let notional = 1_000_000.0;
    let commission = broker_config.calculate_commission("ICMARKETS", notional);

    // Expected: 1M * 0.00007 = 70.0
    assert_eq!(commission, 70.0);

    // Test small notional (below potential minimum)
    let small_commission = broker_config.calculate_commission("ICMARKETS", 1000.0);
    // Allow small floating point error
    let expected = 0.07;
    let diff = (small_commission - expected).abs();
    assert!(
        diff < 0.0001,
        "Commission calculation mismatch: {} vs {}",
        small_commission,
        expected
    );
}

#[test]
fn test_commission_calculation_ibkr_with_minimum() {
    let broker_config = BrokerConfig::default();

    // IBKR: 0.5 bps, $1.0 minimum
    let notional = 1_000_000.0;
    let commission = broker_config.calculate_commission("IBKR", notional);

    // Expected: 1M * 0.00005 = 50.0 (above minimum)
    assert_eq!(commission, 50.0);

    // Test small notional (below minimum)
    let small_notional = 1000.0; // Would be $0.05
    let small_commission = broker_config.calculate_commission("IBKR", small_notional);
    assert_eq!(small_commission, 1.0); // Minimum applied
}

#[test]
fn test_commission_calculation_unknown_broker_fallback() {
    let broker_config = BrokerConfig::default();

    // Unknown broker should use default 1 bps
    let notional = 1_000_000.0;
    let commission = broker_config.calculate_commission("UNKNOWN_BROKER", notional);

    // Expected: 1M * 0.0001 = 100.0
    assert_eq!(commission, 100.0);
}

// ============================================================================
// SECTION 6: Business Logic Tests - Asset Classification (6 tests)
// ============================================================================

#[test]
fn test_asset_classification_explicit_mappings() {
    let config = AssetClassificationConfig::default();

    // Test explicit equity mappings
    assert_eq!(config.classify_symbol("AAPL"), AssetClass::Equities);
    assert_eq!(config.classify_symbol("MSFT"), AssetClass::Equities);
    assert_eq!(config.classify_symbol("GOOGL"), AssetClass::Equities);

    // Test explicit crypto mappings
    assert_eq!(config.classify_symbol("BTC"), AssetClass::Alternatives);
    assert_eq!(config.classify_symbol("ETH"), AssetClass::Alternatives);
    assert_eq!(config.classify_symbol("BTCUSD"), AssetClass::Alternatives);
}

#[test]
fn test_asset_classification_pattern_rules() {
    let config = AssetClassificationConfig::default();

    // Test crypto pattern (highest priority 100)
    assert_eq!(config.classify_symbol("BTCUSDT"), AssetClass::Alternatives);
    assert_eq!(config.classify_symbol("ETHEUR"), AssetClass::Alternatives);

    // Test JPY currency pattern (priority 90)
    assert_eq!(config.classify_symbol("USDJPY"), AssetClass::Currencies);
    assert_eq!(config.classify_symbol("EURJPY"), AssetClass::Currencies);

    // Test generic USD currency pattern (priority 80)
    assert_eq!(config.classify_symbol("EURUSD"), AssetClass::Currencies);
    assert_eq!(config.classify_symbol("GBPUSD"), AssetClass::Currencies);
}

#[test]
fn test_asset_classification_priority_ordering() {
    let config = AssetClassificationConfig::default();

    // BTCUSD matches both crypto pattern (100) and USD pattern (80)
    // Should select higher priority (crypto -> Alternatives)
    assert_eq!(config.classify_symbol("BTCUSD"), AssetClass::Alternatives);

    // ETHJPY matches both crypto pattern (100) and JPY pattern (90)
    // Should select higher priority (crypto -> Alternatives)
    assert_eq!(config.classify_symbol("ETHJPY"), AssetClass::Alternatives);
}

#[test]
fn test_asset_classification_default_fallback() {
    let config = AssetClassificationConfig::default();

    // Unknown symbols should fall back to Cash
    assert_eq!(config.classify_symbol("UNKNOWN"), AssetClass::Cash);
    assert_eq!(config.classify_symbol("XYZ123"), AssetClass::Cash);
    assert_eq!(config.classify_symbol("!@#$"), AssetClass::Cash);
}

#[test]
fn test_volatility_profile_retrieval() {
    let config = AssetClassificationConfig::default();

    // Test equity volatility profile
    let equity_profile = config.get_volatility_profile("AAPL");
    assert_eq!(equity_profile.annual_volatility, 0.25);
    assert_eq!(equity_profile.max_position_fraction, 0.20);

    // Test alternatives (crypto) volatility profile
    let crypto_profile = config.get_volatility_profile("BTC");
    assert_eq!(crypto_profile.annual_volatility, 0.80);
    assert_eq!(crypto_profile.max_position_fraction, 0.08);

    // Test currency volatility profile
    let currency_profile = config.get_volatility_profile("EURUSD");
    assert_eq!(currency_profile.annual_volatility, 0.15);
    assert_eq!(currency_profile.max_position_fraction, 0.30);
}

#[test]
fn test_daily_volatility_calculation() {
    let config = AssetClassificationConfig::default();

    // Test daily volatility calculation (annual_vol / sqrt(252))
    let daily_vol_aapl = config.get_daily_volatility("AAPL");
    let expected_daily_vol = 0.25 / 252.0_f64.sqrt();

    // Allow small floating point error
    let diff = (daily_vol_aapl - expected_daily_vol).abs();
    assert!(
        diff < 0.0001,
        "Daily volatility calculation mismatch: {} vs {}",
        daily_vol_aapl,
        expected_daily_vol
    );

    // Test crypto daily volatility
    let daily_vol_btc = config.get_daily_volatility("BTC");
    let expected_btc = 0.80 / 252.0_f64.sqrt();
    let diff_btc = (daily_vol_btc - expected_btc).abs();
    assert!(diff_btc < 0.0001);
}

// ============================================================================
// SECTION 7: Edge Cases and Validation (4 tests)
// ============================================================================

#[test]
fn test_broker_routing_with_empty_symbol() {
    let broker_config = BrokerConfig::default();

    // Empty symbol should fall back to default broker
    let result = broker_config.select_broker("", 100_000.0);
    assert_eq!(result, "IBKR");
}

#[test]
fn test_broker_routing_with_zero_quantity() {
    let broker_config = BrokerConfig::default();

    // Zero quantity should still route correctly
    let result = broker_config.select_broker("BTCUSD", 0.0);
    assert_eq!(result, "ICMARKETS"); // Crypto pattern matches
}

#[test]
fn test_asset_classification_with_lowercase_symbols() {
    let config = AssetClassificationConfig::default();

    // Test lowercase symbols are handled correctly
    assert_eq!(config.classify_symbol("aapl"), AssetClass::Equities);
    assert_eq!(config.classify_symbol("btc"), AssetClass::Alternatives);
    assert_eq!(config.classify_symbol("eurusd"), AssetClass::Currencies);
}

#[test]
fn test_risk_config_tuple_extraction() {
    let config = AssetClassificationConfig::default();

    // Test get_risk_config returns correct tuple
    let (pos_frac, vol_thresh, loss_thresh) = config.get_risk_config("AAPL");
    assert_eq!(pos_frac, 0.20);
    assert_eq!(vol_thresh, 0.025);
    assert_eq!(loss_thresh, 0.03);

    // Test crypto config
    let (crypto_pos, crypto_vol, crypto_loss) = config.get_risk_config("BTC");
    assert_eq!(crypto_pos, 0.08);
    assert_eq!(crypto_vol, 0.15);
    assert_eq!(crypto_loss, 0.05);
}

// ============================================================================
// SECTION 8: Comprehensive Struct Coverage (2 tests)
// ============================================================================

#[test]
fn test_backtesting_configs_complete() {
    // Test BacktestingStrategyConfig
    let strategy_config = BacktestingStrategyConfig::default();
    assert_eq!(strategy_config.commission_rate, 0.0007);
    assert_eq!(strategy_config.slippage_rate, 0.0002);
    assert_eq!(strategy_config.max_position_size, Some(0.2));
    assert_eq!(strategy_config.allow_short_selling, Some(false));

    // Test BacktestingPerformanceConfig
    let perf_config = BacktestingPerformanceConfig::default();
    assert_eq!(perf_config.risk_free_rate, 0.04);
    assert_eq!(perf_config.equity_curve_resolution, 1000);
    assert_eq!(perf_config.enable_advanced_metrics, Some(true));
}

#[test]
fn test_trading_and_market_data_configs() {
    // Test TradingConfig
    let trading_config = TradingConfig::default();
    assert_eq!(trading_config.max_order_size, 1_000_000.0);
    assert_eq!(trading_config.min_order_size, 0.001);
    assert_eq!(trading_config.max_price_deviation, 0.05);
    assert!(!trading_config.enable_symbol_validation);
    assert_eq!(trading_config.max_batch_notional, 10_000_000.0);
    assert_eq!(trading_config.max_position_var, 50_000.0);

    // Test MarketDataConfig
    let market_config = MarketDataConfig::default();
    assert_eq!(market_config.host, "localhost");
    assert_eq!(market_config.websocket_port, 8080);
    assert!(!market_config.use_ssl);
    assert_eq!(market_config.timeout_seconds, 30);
}
