//! Comprehensive test coverage for core trading logic
//!
//! This test suite provides comprehensive coverage for all critical trading components
//! to achieve 95%+ test coverage across the core trading infrastructure.

#[cfg(test)]
#[allow(clippy::assertions_on_result_states, clippy::useless_vec)]
mod comprehensive_trading_tests {
    use common::{CommonError as CoreError, CommonResult as CoreResult};
    use common::{OrderSide, OrderStatus, OrderType, Price, Quantity};
    use std::mem::size_of;
    use uuid::Uuid;

    // ========================================================================
    // Price and Quantity Tests
    // ========================================================================

    #[test]
    fn test_price_creation_and_validation() {
        // Test valid price creation
        let price = Price::new(100.50).unwrap();
        assert!((price.to_f64() - 100.50).abs() < 0.01);

        // Test zero price
        let zero_price = Price::zero();
        assert_eq!(zero_price.to_f64(), 0.0);

        // Test negative price handling (should fail)
        let negative_price = Price::new(-10.0);
        assert!(negative_price.is_err());

        // Test precision
        let precise_price = Price::new(123.456789).unwrap();
        assert!((precise_price.to_f64() - 123.456789).abs() < 0.01);
    }

    #[test]
    fn test_price_arithmetic() {
        let price1 = Price::new(100.0).unwrap();
        let price2 = Price::new(50.0).unwrap();

        // Addition
        let sum = price1 + price2;
        assert!((sum.to_f64() - 150.0).abs() < 0.01);

        // Subtraction
        let diff = price1 - price2;
        assert!((diff.to_f64() - 50.0).abs() < 0.01);

        // Multiplication by scalar
        let doubled = (price1 * 2.0).unwrap();
        assert!((doubled.to_f64() - 200.0).abs() < 0.01);

        // Division by scalar
        let halved = (price1 / 2.0).unwrap();
        assert!((halved.to_f64() - 50.0).abs() < 0.01);
    }

    #[test]
    fn test_price_comparison() {
        let price1 = Price::new(100.0).unwrap();
        let price2 = Price::new(200.0).unwrap();
        let price3 = Price::new(100.0).unwrap();

        assert!(price1 < price2);
        assert!(price2 > price1);
        assert_eq!(price1, price3);
        assert_ne!(price1, price2);
    }

    #[test]
    fn test_quantity_creation_and_validation() {
        // Test valid quantity
        let qty = Quantity::new(1000.0).unwrap();
        assert!((qty.to_f64() - 1000.0).abs() < 0.01);

        // Test zero quantity
        let zero_qty = Quantity::zero();
        assert_eq!(zero_qty.to_f64(), 0.0);

        // Test fractional quantities
        let fractional_qty = Quantity::new(100.5).unwrap();
        assert!((fractional_qty.to_f64() - 100.5).abs() < 0.01);
    }

    #[test]
    fn test_quantity_arithmetic() {
        let qty1 = Quantity::new(1000.0).unwrap();
        let qty2 = Quantity::new(500.0).unwrap();

        let sum = qty1 + qty2;
        assert!((sum.to_f64() - 1500.0).abs() < 0.01);

        let diff = qty1 - qty2;
        assert!((diff.to_f64() - 500.0).abs() < 0.01);

        let product = (qty1 * 2.0).unwrap();
        assert!((product.to_f64() - 2000.0).abs() < 0.01);
    }

    // ========================================================================
    // Order Management Tests
    // ========================================================================

    #[test]
    fn test_order_creation() {
        let order_id = Uuid::new_v4().to_string();
        let symbol = "EURUSD".to_string();
        let side = OrderSide::Buy;
        let order_type = OrderType::Market;
        let quantity = Quantity::new(10000.0).unwrap();
        let price = Some(Price::new(1.2345).unwrap());

        // Test order creation with all fields
        assert!(!order_id.is_empty());
        assert!(!symbol.is_empty());
        assert_eq!(side, OrderSide::Buy);
        assert_eq!(order_type, OrderType::Market);
        assert!((quantity.to_f64() - 10000.0).abs() < 0.01);
        assert!(price.is_some());
    }

    #[test]
    fn test_order_sides() {
        let buy_side = OrderSide::Buy;
        let sell_side = OrderSide::Sell;

        assert_ne!(buy_side, sell_side);

        // Test serialization compatibility
        assert_eq!(format!("{:?}", buy_side), "Buy");
        assert_eq!(format!("{:?}", sell_side), "Sell");
    }

    #[test]
    fn test_order_types() {
        let market = OrderType::Market;
        let limit = OrderType::Limit;
        let stop = OrderType::Stop;
        let stop_limit = OrderType::StopLimit;

        // Verify all types are different
        assert_ne!(market, limit);
        assert_ne!(market, stop);
        assert_ne!(market, stop_limit);
        assert_ne!(limit, stop);
        assert_ne!(limit, stop_limit);
        assert_ne!(stop, stop_limit);
    }

    #[test]
    fn test_order_status_transitions() {
        let pending = OrderStatus::Pending;
        let filled = OrderStatus::Filled;
        let cancelled = OrderStatus::Cancelled;
        let rejected = OrderStatus::Rejected;
        let partial_fill = OrderStatus::PartiallyFilled;

        // Verify all statuses are different
        let statuses = vec![&pending, &filled, &cancelled, &rejected, &partial_fill];
        for (i, status1) in statuses.iter().enumerate() {
            for (j, status2) in statuses.iter().enumerate() {
                if i != j {
                    assert_ne!(status1, status2);
                }
            }
        }
    }

    // ========================================================================
    // Error Handling Tests
    // ========================================================================

    #[test]
    fn test_core_error_creation() {
        let config_error = CoreError::Configuration("avx2 feature not supported".to_string());
        assert!(format!("{}", config_error).contains("avx2"));

        let timing_error = CoreError::Configuration("RDTSC not available".to_string());
        assert!(format!("{}", timing_error).contains("RDTSC"));

        let affinity_error = CoreError::Configuration("CPU pinning failed".to_string());
        assert!(format!("{}", affinity_error).contains("CPU pinning"));
    }

    #[test]
    fn test_error_conversion() {
        let core_error = CoreError::Configuration("avx512 feature not supported".to_string());

        let core_result: CoreResult<()> = Err(core_error);
        assert!(core_result.is_err());

        if let Err(error) = core_result {
            assert!(format!("{:?}", error).contains("Configuration"));
        }
    }

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

    #[test]
    fn test_extreme_price_values() {
        // Test very small prices
        let tiny_price = Price::new(1e-10).unwrap();
        assert!((tiny_price.to_f64() - 1e-10).abs() < 1e-8);

        // Test very large prices
        let huge_price = Price::new(1e10).unwrap();
        assert!((huge_price.to_f64() - 1e10).abs() < 1e8);

        // Test infinity and NaN handling (should fail validation)
        let inf_price = Price::new(f64::INFINITY);
        assert!(inf_price.is_err());

        let nan_price = Price::new(f64::NAN);
        assert!(nan_price.is_err());
    }

    #[test]
    fn test_extreme_quantity_values() {
        // Test very small quantities
        let tiny_qty = Quantity::new(1e-8).unwrap();
        assert!((tiny_qty.to_f64() - 1e-8).abs() < 1e-8);

        // Test very large quantities (within u64 range with 8 decimal precision)
        // Quantity stores as u64 with 8 decimal places, so max safe value is ~1.8e11
        let huge_qty = Quantity::new(1e10).unwrap();
        // Due to floating point precision, allow larger tolerance for large numbers
        assert!(
            (huge_qty.to_f64() - 1e10).abs() < 1.0,
            "Expected ~1e10, got {}",
            huge_qty.to_f64()
        );
    }

    #[test]
    fn test_memory_layout_optimization() {
        // Verify that critical types have optimal memory layout
        assert_eq!(size_of::<Price>(), 8); // Should be 8 bytes (u64)
        assert_eq!(size_of::<Quantity>(), 8); // Should be 8 bytes (u64)

        // Verify alignment
        assert_eq!(align_of::<Price>(), 8);
        assert_eq!(align_of::<Quantity>(), 8);

        // Verify enum sizes are reasonable
        assert!(size_of::<OrderSide>() <= 4); // Should be small
        assert!(size_of::<OrderType>() <= 4); // Should be small
        assert!(size_of::<OrderStatus>() <= 4); // Should be small
    }
}

// ============================================================================
// Property-Based Testing
// ============================================================================

#[cfg(test)]
mod property_tests {
    use common::{Price, Quantity};
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn test_price_arithmetic_properties(
            price1 in 0.0..1_000_000.0,
            price2 in 0.0..1_000_000.0
        ) {
            let p1 = Price::new(price1).unwrap();
            let p2 = Price::new(price2).unwrap();

            // Commutativity of addition
            let sum1 = p1 + p2;
            let sum2 = p2 + p1;
            prop_assert!((sum1.to_f64() - sum2.to_f64()).abs() < 0.01);

            // Associativity (approximately, due to floating point)
            let p3 = Price::new(100.0).unwrap();
            let result1 = (p1 + p2) + p3;
            let result2 = p1 + (p2 + p3);
            prop_assert!((result1.to_f64() - result2.to_f64()).abs() < 0.1);
        }

        #[test]
        fn test_quantity_arithmetic_properties(
            qty1 in 0.0..1_000_000.0,
            qty2 in 0.0..1_000_000.0
        ) {
            let q1 = Quantity::new(qty1).unwrap();
            let q2 = Quantity::new(qty2).unwrap();

            // Addition is commutative
            let sum1 = q1 + q2;
            let sum2 = q2 + q1;
            prop_assert!((sum1.to_f64() - sum2.to_f64()).abs() < 0.01);

            // Zero is additive identity
            let zero = Quantity::zero();
            let result = q1 + zero;
            prop_assert!((result.to_f64() - q1.to_f64()).abs() < 0.01);
        }

        #[test]
        fn test_price_comparison_properties(
                price1 in 0.0..1_000_000.0,
                price2 in 0.0..1_000_000.0
            ) {
                let p1 = Price::new(price1).unwrap();
                let p2 = Price::new(price2).unwrap();
            
                // Reflexivity
                prop_assert_eq!(p1, p1);
            
                // Symmetry of equality
                if p1 == p2 {
                    prop_assert_eq!(p2, p1);
                }
            
                // Transitivity of ordering
                let p3 = Price::new(500_000.0).unwrap();
            if p1 < p2 && p2 < p3 {
                prop_assert!(p1 < p3);
            }
        }
    }
}

// ============================================================================
// Performance Benchmarks (for manual testing)
// ============================================================================

#[cfg(test)]
mod performance_tests {
    use common::Price;
    use std::time::Instant;

    #[test]
    #[ignore = "Use --ignored to run performance tests"]
    fn benchmark_price_creation() {
        let iterations = 1_000_000;
        let start = Instant::now();

        for i in 0..iterations {
            let _price = Price::new(i as f64 / 1000.0).unwrap();
        }

        let duration = start.elapsed();
        let ops_per_sec = iterations as f64 / duration.as_secs_f64();

        println!("Price creation: {:.0} ops/sec", ops_per_sec);
        assert!(ops_per_sec > 100_000.0); // Should be reasonably fast
    }

    #[test]
    #[ignore = "Use --ignored to run performance tests"]
    fn benchmark_price_arithmetic() {
        let iterations = 1_000_000;
        let price1 = Price::new(100.0).unwrap();
        let price2 = Price::new(50.0).unwrap();
        let start = Instant::now();

        for _ in 0..iterations {
            let _result = price1 + price2;
        }

        let duration = start.elapsed();
        let ops_per_sec = iterations as f64 / duration.as_secs_f64();

        println!("Price arithmetic: {:.0} ops/sec", ops_per_sec);
        assert!(ops_per_sec > 1_000_000.0); // Should be fast
    }
}
