//! Common data types used across services
//!
//! This module provides shared data types that are used throughout
//! the Foxhunt HFT trading system. This includes both infrastructure types
//! and core trading types migrated from foxhunt-common-types.

mod aliases;
mod domain;
mod events;
mod identifiers;
mod market;
mod market_data;
mod service;
mod trading_enums;
mod type_error;

pub use aliases::*;
pub use domain::*;
pub use events::*;
pub use identifiers::*;
pub use market::*;
pub use market_data::*;
pub use service::*;
pub use trading_enums::*;
pub use type_error::*;

// =============================================================================
// COMPREHENSIVE TESTS
// =============================================================================

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::FromStr;

    // =============================================================================
    // Price Tests
    // =============================================================================

    #[test]
    fn test_price_from_f64_valid() {
        let price = Price::from_f64(100.50).unwrap();
        assert_eq!(price.to_f64(), 100.50);
    }

    #[test]
    fn test_price_from_f64_negative() {
        let result = Price::from_f64(-10.0);
        assert!(result.is_err());
    }

    #[test]
    fn test_price_from_f64_nan() {
        let result = Price::from_f64(f64::NAN);
        assert!(result.is_err());
    }

    #[test]
    fn test_price_from_f64_infinity() {
        let result = Price::from_f64(f64::INFINITY);
        assert!(result.is_err());
    }

    #[test]
    fn test_price_constants() {
        assert_eq!(Price::ZERO.to_f64(), 0.0);
        assert_eq!(Price::ONE.to_f64(), 1.0);
        assert_eq!(Price::CENT.to_f64(), 0.01);
    }

    #[test]
    fn test_price_addition() {
        let p1 = Price::from_f64(10.0).unwrap();
        let p2 = Price::from_f64(5.5).unwrap();
        let result = p1 + p2;
        assert!((result.to_f64() - 15.5).abs() < 0.00001);
    }

    #[test]
    fn test_price_subtraction() {
        let p1 = Price::from_f64(10.0).unwrap();
        let p2 = Price::from_f64(5.5).unwrap();
        let result = p1 - p2;
        assert!((result.to_f64() - 4.5).abs() < 0.00001);
    }

    #[test]
    fn test_price_multiplication() {
        let price = Price::from_f64(10.0).unwrap();
        let result = (price * 2.5).unwrap();
        assert!((result.to_f64() - 25.0).abs() < 0.00001);
    }

    #[test]
    fn test_price_division() {
        let price = Price::from_f64(10.0).unwrap();
        let result = (price / 2.0).unwrap();
        assert!((result.to_f64() - 5.0).abs() < 0.00001);
    }

    #[test]
    fn test_price_division_by_zero() {
        let price = Price::from_f64(10.0).unwrap();
        let result = price / 0.0;
        assert!(result.is_err());
    }

    #[test]
    fn test_price_from_cents() {
        let price = Price::from_cents(150);
        assert!((price.to_f64() - 1.50).abs() < 0.00001);
    }

    #[test]
    fn test_price_to_cents() {
        let price = Price::from_f64(1.50).unwrap();
        assert_eq!(price.to_cents(), 150);
    }

    #[test]
    fn test_price_is_zero() {
        assert!(Price::ZERO.is_zero());
        assert!(!Price::from_f64(1.0).unwrap().is_zero());
    }

    #[test]
    fn test_price_from_str() {
        let price = Price::from_str("123.45").unwrap();
        assert!((price.to_f64() - 123.45).abs() < 0.00001);
    }

    #[test]
    fn test_price_from_str_invalid() {
        let result = Price::from_str("invalid");
        assert!(result.is_err());
    }

    #[test]
    fn test_price_display() {
        let price = Price::from_f64(123.456789).unwrap();
        let display = format!("{}", price);
        assert!(display.starts_with("123.45678"));
    }

    #[test]
    fn test_price_partial_eq_f64() {
        let price = Price::from_f64(10.0).unwrap();
        assert_eq!(price, 10.0);
        assert_eq!(10.0, price);
    }

    #[test]
    fn test_price_multiply_price() {
        let p1 = Price::from_f64(10.0).unwrap();
        let p2 = Price::from_f64(2.5).unwrap();
        let result = p1.multiply(p2).unwrap();
        assert!((result.to_f64() - 25.0).abs() < 0.00001);
    }

    // =============================================================================
    // Quantity Tests
    // =============================================================================

    #[test]
    fn test_quantity_from_f64_valid() {
        let qty = Quantity::from_f64(100.5).unwrap();
        assert_eq!(qty.to_f64(), 100.5);
    }

    #[test]
    fn test_quantity_from_f64_negative() {
        let result = Quantity::from_f64(-10.0);
        assert!(result.is_err());
    }

    #[test]
    fn test_quantity_from_f64_nan() {
        let result = Quantity::from_f64(f64::NAN);
        assert!(result.is_err());
    }

    #[test]
    fn test_quantity_constants() {
        assert_eq!(Quantity::ZERO.to_f64(), 0.0);
        assert_eq!(Quantity::ONE.to_f64(), 1.0);
    }

    #[test]
    fn test_quantity_addition() {
        let q1 = Quantity::from_f64(10.0).unwrap();
        let q2 = Quantity::from_f64(5.5).unwrap();
        let result = q1 + q2;
        assert!((result.to_f64() - 15.5).abs() < 0.00001);
    }

    #[test]
    fn test_quantity_subtraction() {
        let q1 = Quantity::from_f64(10.0).unwrap();
        let q2 = Quantity::from_f64(5.5).unwrap();
        let result = q1 - q2;
        assert!((result.to_f64() - 4.5).abs() < 0.00001);
    }

    #[test]
    fn test_quantity_multiplication() {
        let qty = Quantity::from_f64(10.0).unwrap();
        let result = (qty * 2.5).unwrap();
        assert!((result.to_f64() - 25.0).abs() < 0.00001);
    }

    #[test]
    fn test_quantity_division() {
        let qty = Quantity::from_f64(10.0).unwrap();
        let result = (qty / 2.0).unwrap();
        assert!((result.to_f64() - 5.0).abs() < 0.00001);
    }

    #[test]
    fn test_quantity_division_by_zero() {
        let qty = Quantity::from_f64(10.0).unwrap();
        let result = qty / 0.0;
        assert!(result.is_err());
    }

    #[test]
    fn test_quantity_is_zero() {
        assert!(Quantity::ZERO.is_zero());
        assert!(!Quantity::from_f64(1.0).unwrap().is_zero());
    }

    #[test]
    fn test_quantity_is_positive() {
        assert!(Quantity::from_f64(1.0).unwrap().is_positive());
        assert!(!Quantity::ZERO.is_positive());
    }

    #[test]
    fn test_quantity_is_negative() {
        // Quantity is always non-negative
        assert!(!Quantity::from_f64(1.0).unwrap().is_negative());
        assert!(!Quantity::ZERO.is_negative());
    }

    #[test]
    fn test_quantity_from_shares() {
        let qty = Quantity::from_shares(100);
        assert_eq!(qty.to_shares(), 100);
    }

    #[test]
    fn test_quantity_sum() {
        let quantities = vec![
            Quantity::from_f64(1.0).unwrap(),
            Quantity::from_f64(2.0).unwrap(),
            Quantity::from_f64(3.0).unwrap(),
        ];
        let sum: Quantity = quantities.into_iter().sum();
        assert!((sum.to_f64() - 6.0).abs() < 0.00001);
    }

    #[test]
    fn test_quantity_try_from_i32() {
        let qty = Quantity::try_from(100i32).unwrap();
        assert_eq!(qty.to_f64(), 100.0);
    }

    #[test]
    fn test_quantity_try_from_string() {
        let qty = Quantity::try_from("123.45").unwrap();
        assert!((qty.to_f64() - 123.45).abs() < 0.00001);
    }

    // =============================================================================
    // Money Tests
    // =============================================================================

    #[test]
    fn test_money_new() {
        let amount = rust_decimal::Decimal::from_f64_retain(100.50).unwrap();
        let money = Money::new(amount, Currency::USD);
        assert_eq!(money.currency, Currency::USD);
        assert_eq!(money.amount, amount);
    }

    #[test]
    fn test_money_display() {
        let amount = rust_decimal::Decimal::from_f64_retain(100.50).unwrap();
        let money = Money::new(amount, Currency::USD);
        let display = format!("{}", money);
        assert!(display.contains("100.5"));
        assert!(display.contains("USD"));
    }

    // =============================================================================
    // Symbol Tests
    // =============================================================================

    #[test]
    fn test_symbol_new() {
        let symbol = Symbol::new("AAPL".to_owned());
        assert_eq!(symbol.as_str(), "AAPL");
    }

    #[test]
    fn test_symbol_new_validated_valid() {
        let symbol = Symbol::new_validated("AAPL".to_owned()).unwrap();
        assert_eq!(symbol.as_str(), "AAPL");
    }

    #[test]
    fn test_symbol_new_validated_empty() {
        let result = Symbol::new_validated("".to_owned());
        assert!(result.is_err());
    }

    #[test]
    fn test_symbol_new_validated_whitespace() {
        let result = Symbol::new_validated("   ".to_owned());
        assert!(result.is_err());
    }

    #[test]
    fn test_symbol_from_str() {
        let symbol = Symbol::from_str("AAPL").unwrap();
        assert_eq!(symbol.as_str(), "AAPL");
    }

    #[test]
    fn test_symbol_to_uppercase() {
        let symbol = Symbol::from_str("aapl").unwrap();
        assert_eq!(symbol.to_uppercase(), "AAPL");
    }

    #[test]
    fn test_symbol_replace() {
        let symbol = Symbol::from_str("AAPL.US").unwrap();
        assert_eq!(symbol.replace(".US", ""), "AAPL");
    }

    #[test]
    fn test_symbol_contains() {
        let symbol = Symbol::from_str("AAPL.US").unwrap();
        assert!(symbol.contains("AAPL"));
        assert!(!symbol.contains("MSFT"));
    }

    #[test]
    fn test_symbol_partial_eq_str() {
        let symbol = Symbol::from_str("AAPL").unwrap();
        assert_eq!("AAPL", symbol);
        assert_eq!(symbol.as_str(), "AAPL");
    }

    #[test]
    fn test_symbol_none() {
        let symbol = Symbol::none();
        assert_eq!(symbol.as_str(), "NONE");
    }

    // =============================================================================
    // TimeInForce Tests
    // =============================================================================

    #[test]
    fn test_time_in_force_display() {
        assert_eq!(format!("{}", TimeInForce::Day), "DAY");
        assert_eq!(format!("{}", TimeInForce::GoodTillCancel), "GTC");
        assert_eq!(format!("{}", TimeInForce::ImmediateOrCancel), "IOC");
        assert_eq!(format!("{}", TimeInForce::FillOrKill), "FOK");
    }

    #[test]
    fn test_time_in_force_default() {
        assert_eq!(TimeInForce::default(), TimeInForce::Day);
    }

    // =============================================================================
    // OrderType Tests
    // =============================================================================

    #[test]
    fn test_order_type_display() {
        assert_eq!(format!("{}", OrderType::Market), "MARKET");
        assert_eq!(format!("{}", OrderType::Limit), "LIMIT");
        assert_eq!(format!("{}", OrderType::Stop), "STOP");
        assert_eq!(format!("{}", OrderType::StopLimit), "STOP_LIMIT");
    }

    #[test]
    fn test_order_type_try_from_i32_valid() {
        assert_eq!(OrderType::try_from(0).unwrap(), OrderType::Market);
        assert_eq!(OrderType::try_from(1).unwrap(), OrderType::Limit);
        assert_eq!(OrderType::try_from(2).unwrap(), OrderType::Stop);
    }

    #[test]
    fn test_order_type_try_from_i32_invalid() {
        let result = OrderType::try_from(99);
        assert!(result.is_err());
    }

    #[test]
    fn test_order_type_default() {
        assert_eq!(OrderType::default(), OrderType::Market);
    }

    // =============================================================================
    // OrderStatus Tests
    // =============================================================================

    #[test]
    fn test_order_status_display() {
        assert_eq!(format!("{}", OrderStatus::Created), "CREATED");
        assert_eq!(format!("{}", OrderStatus::Filled), "FILLED");
        assert_eq!(format!("{}", OrderStatus::Cancelled), "CANCELLED");
    }

    #[test]
    fn test_order_status_try_from_i32_valid() {
        assert_eq!(OrderStatus::try_from(0).unwrap(), OrderStatus::Created);
        assert_eq!(OrderStatus::try_from(3).unwrap(), OrderStatus::Filled);
        assert_eq!(OrderStatus::try_from(5).unwrap(), OrderStatus::Cancelled);
    }

    #[test]
    fn test_order_status_try_from_i32_invalid() {
        let result = OrderStatus::try_from(99);
        assert!(result.is_err());
    }

    // =============================================================================
    // OrderSide Tests
    // =============================================================================

    #[test]
    fn test_order_side_display() {
        assert_eq!(format!("{}", OrderSide::Buy), "BUY");
        assert_eq!(format!("{}", OrderSide::Sell), "SELL");
    }

    #[test]
    fn test_order_side_try_from_i32_valid() {
        assert_eq!(OrderSide::try_from(0).unwrap(), OrderSide::Buy);
        assert_eq!(OrderSide::try_from(1).unwrap(), OrderSide::Sell);
    }

    #[test]
    fn test_order_side_try_from_i32_invalid() {
        let result = OrderSide::try_from(99);
        assert!(result.is_err());
    }

    #[test]
    fn test_order_side_default() {
        assert_eq!(OrderSide::default(), OrderSide::Buy);
    }

    // =============================================================================
    // Currency Tests
    // =============================================================================

    #[test]
    fn test_currency_display() {
        assert_eq!(format!("{}", Currency::USD), "USD");
        assert_eq!(format!("{}", Currency::EUR), "EUR");
        assert_eq!(format!("{}", Currency::BTC), "BTC");
    }

    #[test]
    fn test_currency_default() {
        assert_eq!(Currency::default(), Currency::USD);
    }

    // =============================================================================
    // Error Type Tests
    // =============================================================================

    #[test]
    fn test_common_type_error_invalid_price() {
        let error = CommonTypeError::InvalidPrice {
            value: "abc".to_owned(),
            reason: "not a number".to_owned(),
        };
        let display = format!("{}", error);
        assert!(display.contains("abc"));
    }

    #[test]
    fn test_common_type_error_invalid_quantity() {
        let error = CommonTypeError::InvalidQuantity {
            value: "xyz".to_owned(),
            reason: "not a number".to_owned(),
        };
        let display = format!("{}", error);
        assert!(display.contains("xyz"));
    }

    #[test]
    fn test_common_type_error_validation() {
        let error = CommonTypeError::ValidationError {
            field: "symbol".to_owned(),
            reason: "cannot be empty".to_owned(),
        };
        let display = format!("{}", error);
        assert!(display.contains("symbol"));
    }
}
