//! Comprehensive validation edge cases tests for config package
//!
//! This test suite provides additional edge case coverage for:
//! - ML config validation (SimulationConfig, TrainingConfig)
//! - Risk config validation (StressScenarioConfig, AssetClassMapping)
//! - Broker config validation (routing rules, commission rates)
//! - URL parsing and malformed input handling
//! - Numeric overflow and boundary conditions
//! - String edge cases (Unicode, special chars, empty strings)
//! - Deserialization edge cases (malformed JSON/TOML)
//! - Environment variable parsing edge cases

use config::{
    database::DatabaseConfig,
    ml_config::{MarketCapTier, MarketState, SimulationConfig, SymbolConfig as MLSymbolConfig},
    risk_config::{
        AssetClass as RiskAssetClass, AssetClassMapping, RiskConfig as RiskConfigV2,
        StressScenarioConfig,
    },
    runtime::{DatabaseRuntimeConfig, Environment, LimitsConfig, TimeoutConfig},
    schemas::{AssetClassificationSchema, S3Config},
    structures::{
        BrokerConfig, BrokerRoutingRule, CircuitBreakerConfig, CommissionConfig, KellyConfig,
        PositionLimitsConfig, VarConfig,
    },
};
use std::collections::HashMap;
use std::time::Duration;

// ============================================================================
// ML Config Validation Tests
// ============================================================================

#[test]
fn test_simulation_config_negative_price() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.initial_price = -100.0;

    // Negative prices are structurally allowed but economically invalid
    // In production, this should be validated
    assert_eq!(
        config.initial_market_state.default_symbol.initial_price,
        -100.0
    );
}

#[test]
fn test_simulation_config_zero_price() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.initial_price = 0.0;

    // Zero prices are structurally allowed
    assert_eq!(
        config.initial_market_state.default_symbol.initial_price,
        0.0
    );
}

#[test]
fn test_simulation_config_infinity_price() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.initial_price = f64::INFINITY;

    // Infinity is structurally allowed (serde serializes it)
    assert!(config
        .initial_market_state
        .default_symbol
        .initial_price
        .is_infinite());
}

#[test]
fn test_simulation_config_nan_price() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.initial_price = f64::NAN;

    // NaN is structurally allowed
    assert!(config
        .initial_market_state
        .default_symbol
        .initial_price
        .is_nan());
}

#[test]
fn test_simulation_config_negative_volatility() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.volatility = -0.5;

    // Negative volatility is economically invalid but structurally allowed
    assert_eq!(config.initial_market_state.default_symbol.volatility, -0.5);
}

#[test]
fn test_simulation_config_extreme_volatility() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.volatility = 100.0; // 10,000% volatility

    // Extreme volatility is structurally allowed
    assert_eq!(config.initial_market_state.default_symbol.volatility, 100.0);
}

#[test]
fn test_simulation_config_negative_volume() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.base_volume = -1000000.0;

    // Negative volume is economically invalid but structurally allowed
    assert_eq!(
        config.initial_market_state.default_symbol.base_volume,
        -1000000.0
    );
}

#[test]
fn test_simulation_config_spread_min_greater_than_max() {
    let mut config = SimulationConfig::default();
    config.initial_market_state.default_symbol.min_spread_bps = 50.0;
    config.initial_market_state.default_symbol.max_spread_bps = 10.0;

    // Min > Max is logically invalid but structurally allowed
    assert!(
        config.initial_market_state.default_symbol.min_spread_bps
            > config.initial_market_state.default_symbol.max_spread_bps
    );
}

#[test]
fn test_simulation_parameters_zero_update_rate() {
    let mut config = SimulationConfig::default();
    config.parameters.update_rate_hz = 0;

    // Zero update rate would cause division by zero in interval calculations
    assert_eq!(config.parameters.update_rate_hz, 0);
}

#[test]
fn test_simulation_parameters_extreme_update_rate() {
    let mut config = SimulationConfig::default();
    config.parameters.update_rate_hz = u32::MAX; // ~4 billion Hz

    // Extreme update rate is structurally allowed
    assert_eq!(config.parameters.update_rate_hz, u32::MAX);
}

#[test]
fn test_simulation_parameters_trend_out_of_range() {
    let mut config = SimulationConfig::default();
    config.parameters.trend = 5.0; // Should be -1.0 to 1.0

    // Out-of-range trend is structurally allowed
    assert_eq!(config.parameters.trend, 5.0);
}

#[test]
fn test_test_symbol_config_zero_count() {
    let mut config = SimulationConfig::default();
    config.test_symbols.count = 0;

    // Zero symbols is valid (no test symbols generated)
    assert_eq!(config.test_symbols.count, 0);
}

#[test]
fn test_test_symbol_config_extreme_count() {
    let mut config = SimulationConfig::default();
    config.test_symbols.count = usize::MAX;

    // Extreme count would exhaust memory but is structurally allowed
    assert_eq!(config.test_symbols.count, usize::MAX);
}

#[test]
fn test_test_symbol_config_inverted_price_range() {
    let mut config = SimulationConfig::default();
    config.test_symbols.price_range = (500.0, 50.0); // Max < Min

    // Inverted range is logically invalid but structurally allowed
    assert!(config.test_symbols.price_range.0 > config.test_symbols.price_range.1);
}

#[test]
fn test_test_symbol_config_negative_price_range() {
    let mut config = SimulationConfig::default();
    config.test_symbols.price_range = (-100.0, -10.0);

    // Negative prices are economically invalid but structurally allowed
    assert!(config.test_symbols.price_range.0 < 0.0);
}

#[test]
fn test_market_state_empty_symbols() {
    let market_state = MarketState {
        symbols: HashMap::new(),
        default_symbol: MLSymbolConfig {
            initial_price: 100.0,
            volatility: 0.3,
            base_volume: 1_000_000.0,
            min_spread_bps: 5.0,
            max_spread_bps: 20.0,
            market_cap_tier: MarketCapTier::Test,
        },
    };

    // Empty symbols map is valid (all symbols use default)
    assert_eq!(market_state.symbols.len(), 0);
}

#[test]
fn test_market_state_duplicate_symbol_keys() {
    let mut symbols = HashMap::new();
    symbols.insert(
        "AAPL".to_string(),
        MLSymbolConfig {
            initial_price: 150.0,
            volatility: 0.25,
            base_volume: 50_000_000.0,
            min_spread_bps: 1.0,
            max_spread_bps: 5.0,
            market_cap_tier: MarketCapTier::LargeCap,
        },
    );
    // HashMap automatically handles duplicates (overwrites)
    symbols.insert(
        "AAPL".to_string(),
        MLSymbolConfig {
            initial_price: 160.0,
            volatility: 0.3,
            base_volume: 60_000_000.0,
            min_spread_bps: 2.0,
            max_spread_bps: 8.0,
            market_cap_tier: MarketCapTier::LargeCap,
        },
    );

    // Second insert overwrites first
    assert_eq!(symbols.get("AAPL").unwrap().initial_price, 160.0);
}

// ============================================================================
// Risk Config Validation Tests
// ============================================================================

#[test]
fn test_stress_scenario_empty_id() {
    let scenario = StressScenarioConfig {
        id: String::new(),
        name: "Test Scenario".to_string(),
        description: "Test".to_string(),
        instrument_shocks: HashMap::new(),
        asset_class_shocks: HashMap::new(),
        volatility_multiplier: 1.5,
        volatility_multipliers: HashMap::new(),
        correlation_adjustments: HashMap::new(),
        liquidity_haircuts: HashMap::new(),
        is_active: true,
    };

    // Empty ID is structurally allowed but should be validated
    assert!(scenario.id.is_empty());
}

#[test]
fn test_stress_scenario_negative_volatility_multiplier() {
    let scenario = StressScenarioConfig {
        id: "test-1".to_string(),
        name: "Test Scenario".to_string(),
        description: "Test".to_string(),
        instrument_shocks: HashMap::new(),
        asset_class_shocks: HashMap::new(),
        volatility_multiplier: -2.0,
        volatility_multipliers: HashMap::new(),
        correlation_adjustments: HashMap::new(),
        liquidity_haircuts: HashMap::new(),
        is_active: true,
    };

    // Negative multiplier is economically invalid
    assert!(scenario.volatility_multiplier < 0.0);
}

#[test]
fn test_stress_scenario_extreme_instrument_shocks() {
    let mut shocks = HashMap::new();
    shocks.insert("AAPL".to_string(), -100.0); // -10,000% shock (total loss + more)
    shocks.insert("MSFT".to_string(), 1000.0); // 100,000% gain

    let scenario = StressScenarioConfig {
        id: "extreme-1".to_string(),
        name: "Extreme Scenario".to_string(),
        description: "Extreme shocks".to_string(),
        instrument_shocks: shocks,
        asset_class_shocks: HashMap::new(),
        volatility_multiplier: 1.0,
        volatility_multipliers: HashMap::new(),
        correlation_adjustments: HashMap::new(),
        liquidity_haircuts: HashMap::new(),
        is_active: true,
    };

    // Extreme shocks are structurally allowed
    assert_eq!(scenario.instrument_shocks.get("AAPL"), Some(&-100.0));
    assert_eq!(scenario.instrument_shocks.get("MSFT"), Some(&1000.0));
}

#[test]
fn test_stress_scenario_liquidity_haircut_greater_than_one() {
    let mut haircuts = HashMap::new();
    haircuts.insert(RiskAssetClass::SmallCapEquity, 1.5); // 150% haircut

    let scenario = StressScenarioConfig {
        id: "liquidity-1".to_string(),
        name: "Liquidity Test".to_string(),
        description: "Test liquidity haircuts".to_string(),
        instrument_shocks: HashMap::new(),
        asset_class_shocks: HashMap::new(),
        volatility_multiplier: 1.0,
        volatility_multipliers: HashMap::new(),
        correlation_adjustments: HashMap::new(),
        liquidity_haircuts: haircuts,
        is_active: true,
    };

    // Haircut > 1.0 means position value goes negative (economically invalid)
    assert!(
        scenario
            .liquidity_haircuts
            .get(&RiskAssetClass::SmallCapEquity)
            .unwrap()
            > &1.0
    );
}

#[test]
fn test_asset_class_mapping_empty_mappings() {
    let mapping = AssetClassMapping {
        mappings: HashMap::new(),
        default_class: RiskAssetClass::Alternatives,
    };

    // Empty mappings is valid (all symbols use default)
    assert_eq!(mapping.mappings.len(), 0);
}

#[test]
fn test_asset_class_mapping_get_unmapped_symbol() {
    let mapping = AssetClassMapping {
        mappings: HashMap::new(),
        default_class: RiskAssetClass::Technology,
    };

    // Unmapped symbol should return None
    assert_eq!(mapping.mappings.get("UNKNOWN"), None);
}

#[test]
fn test_risk_config_negative_var_confidence() {
    let config = RiskConfigV2 {
        stress_scenarios: Vec::new(),
        asset_class_mapping: AssetClassMapping {
            mappings: HashMap::new(),
            default_class: RiskAssetClass::Alternatives,
        },
        default_volatility_multiplier: 1.0,
        max_portfolio_loss_pct: 20.0,
        var_confidence_level: -0.5, // Invalid: should be 0.0-1.0
        var_time_horizon_days: 1,
    };

    // Negative confidence is mathematically invalid
    assert!(config.var_confidence_level < 0.0);
}

#[test]
fn test_risk_config_var_confidence_greater_than_one() {
    let config = RiskConfigV2 {
        stress_scenarios: Vec::new(),
        asset_class_mapping: AssetClassMapping {
            mappings: HashMap::new(),
            default_class: RiskAssetClass::Alternatives,
        },
        default_volatility_multiplier: 1.0,
        max_portfolio_loss_pct: 20.0,
        var_confidence_level: 1.5, // Invalid: should be 0.0-1.0
        var_time_horizon_days: 1,
    };

    // Confidence > 1.0 is mathematically invalid
    assert!(config.var_confidence_level > 1.0);
}

#[test]
fn test_risk_config_zero_time_horizon() {
    let config = RiskConfigV2 {
        stress_scenarios: Vec::new(),
        asset_class_mapping: AssetClassMapping {
            mappings: HashMap::new(),
            default_class: RiskAssetClass::Alternatives,
        },
        default_volatility_multiplier: 1.0,
        max_portfolio_loss_pct: 20.0,
        var_confidence_level: 0.95,
        var_time_horizon_days: 0, // Zero horizon is invalid
    };

    // Zero time horizon makes no economic sense
    assert_eq!(config.var_time_horizon_days, 0);
}

// ============================================================================
// Broker Config Validation Tests
// ============================================================================

#[test]
fn test_broker_config_empty_routing_rules() {
    let config = BrokerConfig {
        routing_rules: Vec::new(),
        default_broker: "IBKR".to_string(),
        commission_rates: HashMap::new(),
    };

    // Empty rules is valid (falls back to default broker)
    assert_eq!(config.routing_rules.len(), 0);
}

#[test]
fn test_broker_config_empty_default_broker() {
    let config = BrokerConfig {
        routing_rules: Vec::new(),
        default_broker: String::new(),
        commission_rates: HashMap::new(),
    };

    // Empty default broker would cause issues but is structurally allowed
    assert!(config.default_broker.is_empty());
}

#[test]
fn test_broker_routing_rule_invalid_regex() {
    let rule = BrokerRoutingRule {
        priority: 100,
        symbol_pattern: "[invalid(regex".to_string(), // Invalid regex
        min_quantity: None,
        max_quantity: None,
        broker_id: "IBKR".to_string(),
        description: "Test invalid regex".to_string(),
    };

    // Invalid regex is structurally allowed (fails at runtime)
    assert!(regex::Regex::new(&rule.symbol_pattern).is_err());
}

#[test]
fn test_broker_routing_rule_min_greater_than_max_quantity() {
    let rule = BrokerRoutingRule {
        priority: 100,
        symbol_pattern: ".*".to_string(),
        min_quantity: Some(1_000_000.0),
        max_quantity: Some(10_000.0), // Min > Max
        broker_id: "IBKR".to_string(),
        description: "Test invalid quantity range".to_string(),
    };

    // Inverted range is logically invalid
    assert!(rule.min_quantity.unwrap() > rule.max_quantity.unwrap());
}

#[test]
fn test_broker_routing_rule_negative_quantity() {
    let rule = BrokerRoutingRule {
        priority: 100,
        symbol_pattern: ".*".to_string(),
        min_quantity: Some(-10_000.0),
        max_quantity: Some(-1_000.0),
        broker_id: "IBKR".to_string(),
        description: "Test negative quantities".to_string(),
    };

    // Negative quantities are economically invalid
    assert!(rule.min_quantity.unwrap() < 0.0);
}

#[test]
fn test_commission_config_negative_rate() {
    let config = CommissionConfig {
        rate_bps: -0.00005, // Negative commission (broker pays you)
        min_commission: 1.0,
    };

    // Negative rate is economically unusual but structurally allowed
    assert!(config.rate_bps < 0.0);
}

#[test]
fn test_commission_config_negative_min_commission() {
    let config = CommissionConfig {
        rate_bps: 0.00005,
        min_commission: -10.0, // Negative minimum
    };

    // Negative minimum is economically invalid
    assert!(config.min_commission < 0.0);
}

#[test]
fn test_commission_config_extreme_rate() {
    let config = CommissionConfig {
        rate_bps: 100.0, // 10,000 bps = 100% commission
        min_commission: 0.0,
    };

    // 100% commission is economically absurd but structurally allowed
    assert_eq!(config.rate_bps, 100.0);
}

// ============================================================================
// Structure Config Validation Tests
// ============================================================================

#[test]
fn test_var_config_confidence_at_boundaries() {
    let config_zero = VarConfig {
        confidence_level: 0.0,
        ..VarConfig::default()
    };
    let config_one = VarConfig {
        confidence_level: 1.0,
        ..VarConfig::default()
    };

    // Boundaries are mathematically valid
    assert_eq!(config_zero.confidence_level, 0.0);
    assert_eq!(config_one.confidence_level, 1.0);
}

#[test]
fn test_var_config_negative_lookback_period() {
    // u32 can't be negative, but testing zero
    let config = VarConfig {
        lookback_period_days: 0,
        ..VarConfig::default()
    };

    // Zero lookback makes no sense
    assert_eq!(config.lookback_period_days, 0);
}

#[test]
fn test_var_config_empty_calculation_method() {
    let config = VarConfig {
        calculation_method: String::new(),
        ..VarConfig::default()
    };

    // Empty method is structurally allowed but should be validated
    assert!(config.calculation_method.is_empty());
}

#[test]
fn test_var_config_unknown_calculation_method() {
    let config = VarConfig {
        calculation_method: "quantum_flux_capacitor".to_string(),
        ..VarConfig::default()
    };

    // Unknown method is structurally allowed
    assert_eq!(config.calculation_method, "quantum_flux_capacitor");
}

#[test]
fn test_kelly_config_negative_fraction() {
    let config = KellyConfig {
        kelly_fraction: -0.5,
        ..KellyConfig::default()
    };

    // Negative Kelly fraction is mathematically invalid
    assert!(config.kelly_fraction < 0.0);
}

#[test]
fn test_kelly_config_fraction_greater_than_one() {
    let config = KellyConfig {
        kelly_fraction: 2.0, // 200% Kelly = extreme leverage
        ..KellyConfig::default()
    };

    // Fraction > 1.0 means over-leveraging
    assert!(config.kelly_fraction > 1.0);
}

#[test]
fn test_kelly_config_min_greater_than_max_leverage() {
    let config = KellyConfig {
        min_kelly_leverage: 5.0,
        max_kelly_leverage: 2.0, // Min > Max
        ..KellyConfig::default()
    };

    // Inverted range is logically invalid
    assert!(config.min_kelly_leverage > config.max_kelly_leverage);
}

#[test]
fn test_kelly_config_zero_lookback_periods() {
    let config = KellyConfig {
        lookback_periods: 0,
        ..KellyConfig::default()
    };

    // Zero lookback makes no sense
    assert_eq!(config.lookback_periods, 0);
}

#[test]
fn test_circuit_breaker_negative_threshold() {
    let config = CircuitBreakerConfig {
        enabled: true,
        price_move_threshold: -0.05, // Negative threshold makes no sense
        halt_duration_seconds: 300,
    };

    // Negative threshold is logically invalid
    assert!(config.price_move_threshold < 0.0);
}

#[test]
fn test_circuit_breaker_zero_halt_duration() {
    let config = CircuitBreakerConfig {
        enabled: true,
        price_move_threshold: 0.05,
        halt_duration_seconds: 0, // Zero duration = instant resume
    };

    // Zero duration defeats the purpose but is structurally allowed
    assert_eq!(config.halt_duration_seconds, 0);
}

#[test]
fn test_circuit_breaker_extreme_halt_duration() {
    let config = CircuitBreakerConfig {
        enabled: true,
        price_move_threshold: 0.05,
        halt_duration_seconds: u64::MAX, // ~585 billion years
    };

    // Extreme duration is structurally allowed
    assert_eq!(config.halt_duration_seconds, u64::MAX);
}

#[test]
fn test_position_limits_negative_limits() {
    let config = PositionLimitsConfig {
        global_limit: -10_000_000.0,
        max_leverage: -3.0,
        max_var_limit: -100_000.0,
    };

    // Negative limits are economically invalid
    assert!(config.global_limit < 0.0);
    assert!(config.max_leverage < 0.0);
    assert!(config.max_var_limit < 0.0);
}

#[test]
fn test_position_limits_zero_max_leverage() {
    let config = PositionLimitsConfig {
        global_limit: 10_000_000.0,
        max_leverage: 0.0, // Zero leverage = cash only
        max_var_limit: 100_000.0,
    };

    // Zero leverage is valid (no borrowing)
    assert_eq!(config.max_leverage, 0.0);
}

// ============================================================================
// URL Parsing and Malformed Input Tests
// ============================================================================

#[test]
fn test_s3_config_malformed_endpoint_no_scheme() {
    let config = S3Config {
        endpoint_url: Some("localhost:9000".to_string()), // Missing http://
        ..S3Config::default()
    };

    // Missing scheme is structurally allowed (fails at connection time)
    assert_eq!(config.endpoint_url, Some("localhost:9000".to_string()));
}

#[test]
fn test_s3_config_endpoint_invalid_characters() {
    let config = S3Config {
        endpoint_url: Some("http://local host:9000".to_string()), // Space in URL
        ..S3Config::default()
    };

    // Invalid URL is structurally allowed
    assert!(config.endpoint_url.unwrap().contains(' '));
}

#[test]
fn test_database_config_malformed_url_no_protocol() {
    let config = DatabaseConfig {
        url: "localhost:5432/foxhunt".to_string(), // Missing postgresql://
        ..DatabaseConfig::default()
    };

    // Missing protocol is structurally allowed
    assert!(config.validate().is_ok());
    assert!(!config.url.starts_with("postgresql://"));
}

#[test]
fn test_database_config_url_special_characters() {
    let config = DatabaseConfig {
        url: "postgresql://user:p@ss#word!@localhost:5432/db".to_string(),
        ..DatabaseConfig::default()
    };

    // Special characters in password are valid if properly encoded
    assert!(config.validate().is_ok());
}

#[test]
fn test_database_config_url_unicode_characters() {
    let config = DatabaseConfig {
        url: "postgresql://用户:密码@localhost:5432/数据库".to_string(),
        ..DatabaseConfig::default()
    };

    // Unicode in URL is structurally allowed (may fail at connection)
    assert!(config.validate().is_ok());
}

// ============================================================================
// Deserialization Edge Cases
// ============================================================================

#[test]
fn test_s3_config_json_deserialization_with_nulls() {
    let json = r#"{
        "bucket_name": "test-bucket",
        "region": "us-east-1",
        "access_key_id": null,
        "secret_access_key": null,
        "session_token": null,
        "endpoint_url": null,
        "force_path_style": false,
        "timeout": {"secs": 30, "nanos": 0},
        "max_retry_attempts": 3,
        "use_ssl": true
    }"#;

    let result: Result<S3Config, _> = serde_json::from_str(json);
    assert!(result.is_ok());
    let config = result.unwrap();
    assert!(config.access_key_id.is_none());
}

#[test]
fn test_s3_config_json_deserialization_missing_optional_fields() {
    let json = r#"{
        "bucket_name": "test-bucket",
        "region": "us-east-1",
        "force_path_style": false,
        "timeout": {"secs": 30, "nanos": 0},
        "max_retry_attempts": 3,
        "use_ssl": true
    }"#;

    let result: Result<S3Config, _> = serde_json::from_str(json);
    assert!(result.is_ok());
    let config = result.unwrap();
    assert!(config.access_key_id.is_none());
}

#[test]
fn test_s3_config_json_deserialization_wrong_types() {
    let json = r#"{
        "bucket_name": "test-bucket",
        "region": "us-east-1",
        "force_path_style": false,
        "timeout": {"secs": 30, "nanos": 0},
        "max_retry_attempts": "three",
        "use_ssl": true
    }"#;

    // String instead of u32 should fail deserialization
    let result: Result<S3Config, _> = serde_json::from_str(json);
    assert!(result.is_err());
}

#[test]
fn test_database_config_json_with_extra_fields() {
    let json = r#"{
        "url": "postgresql://localhost/db",
        "max_connections": 10,
        "min_connections": 1,
        "connect_timeout": {"secs": 30, "nanos": 0},
        "query_timeout": {"secs": 60, "nanos": 0},
        "enable_query_logging": false,
        "application_name": "test",
        "pool": {
            "min_connections": 1,
            "max_connections": 10,
            "acquire_timeout_secs": 30,
            "max_lifetime_secs": 3600,
            "idle_timeout_secs": 3600,
            "test_before_acquire": true,
            "database_url": "postgresql://localhost/db",
            "health_check_enabled": true,
            "health_check_interval_secs": 60
        },
        "transaction": {
            "isolation_level": "READ_COMMITTED",
            "timeout": {"secs": 30, "nanos": 0},
            "default_timeout_secs": 30,
            "enable_retry": true,
            "max_retries": 3,
            "retry_delay_ms": 100,
            "max_savepoints": 10
        }
    }"#;

    // Should deserialize successfully with correct field names
    let result: Result<DatabaseConfig, _> = serde_json::from_str(json);
    assert!(result.is_ok(), "Failed to deserialize: {:?}", result.err());
}

#[test]
fn test_asset_classification_schema_json_empty_patterns() {
    let json = r#"{
        "asset_type_rules": {},
        "default_sectors": {},
        "currency_patterns": [],
        "crypto_patterns": []
    }"#;

    let result: Result<AssetClassificationSchema, _> = serde_json::from_str(json);
    assert!(result.is_ok());
    let schema = result.unwrap();
    assert_eq!(schema.currency_patterns.len(), 0);
}

// ============================================================================
// Timeout Configuration Edge Cases
// ============================================================================

#[test]
fn test_timeout_config_duration_overflow() {
    // Duration::MAX is ~584 years - structurally valid but may not have validation
    let config = TimeoutConfig {
        grpc_connect_timeout: Duration::MAX,
        grpc_request_timeout: Duration::MAX,
        keep_alive_interval: Duration::MAX,
        keep_alive_timeout: Duration::MAX,
        max_concurrent_connections: 100,
    };

    // Extreme durations are structurally allowed (no upper bound validation currently)
    // In production, these would timeout at connection time
    assert_eq!(config.grpc_connect_timeout, Duration::MAX);
}

#[test]
fn test_database_runtime_config_very_short_timeouts() {
    let config = DatabaseRuntimeConfig {
        query_timeout: Duration::from_nanos(1), // 1 nanosecond
        connection_timeout: Duration::from_nanos(1),
        acquire_timeout: Duration::from_nanos(1),
        ..DatabaseRuntimeConfig::with_defaults(Environment::Development)
    };

    // Very short timeouts are structurally allowed
    assert_eq!(config.query_timeout.as_nanos(), 1);
}

// ============================================================================
// Limits Configuration Edge Cases
// ============================================================================

#[test]
fn test_limits_config_extreme_batch_size() {
    let config = LimitsConfig {
        ml_max_batch_size: usize::MAX,
        ..LimitsConfig::with_defaults(Environment::Development)
    };

    // Extreme batch size would exhaust memory but passes structural validation
    // Validation only checks > 0, not upper bounds
    let result = config.validate();
    assert!(
        result.is_ok(),
        "Extreme batch size should be structurally valid"
    );
    assert_eq!(config.ml_max_batch_size, usize::MAX);
}

#[test]
fn test_limits_config_var_confidence_boundary_conditions() {
    // Test exactly at boundaries (0.0 and 1.0)
    let config_zero = LimitsConfig {
        risk_var_confidence: 0.0,
        ..LimitsConfig::with_defaults(Environment::Development)
    };
    let config_one = LimitsConfig {
        risk_var_confidence: 1.0,
        ..LimitsConfig::with_defaults(Environment::Development)
    };

    // Boundaries should be valid
    assert!(config_zero.validate().is_ok());
    assert!(config_one.validate().is_ok());
}

#[test]
fn test_limits_config_var_confidence_epsilon_outside_bounds() {
    let config_below = LimitsConfig {
        risk_var_confidence: -f64::EPSILON,
        ..LimitsConfig::with_defaults(Environment::Development)
    };
    let config_above = LimitsConfig {
        risk_var_confidence: 1.0 + f64::EPSILON,
        ..LimitsConfig::with_defaults(Environment::Development)
    };

    // Even epsilon outside bounds should fail
    assert!(config_below.validate().is_err());
    assert!(config_above.validate().is_err());
}
