//! Compile-time Type System Enforcement
//!
//! This module contains compile-time checks that prevent type system violations.

use crate::basic::*;

// ============================================================================
// TYPE UNIQUENESS ASSERTIONS
// ============================================================================

/// Compile-time assertion that ensures only one Price definition exists
const _PRICE_UNIQUENESS_CHECK: () = {
    let _ = || -> Result<(), Box<dyn std::error::Error>> {
        // This will only compile if Price is uniquely defined
        let price = Price::from_f64(123.45)?;
        let _: f64 = price.to_f64();
        let _: Price = price + price;
        let _: Price = price - price;
        Ok(())
    };
};

/// Compile-time assertion for OrderStatus enum uniqueness
const _ORDER_STATUS_UNIQUENESS_CHECK: () = {
    let _ = || {
        let _: OrderStatus = OrderStatus::Pending;
        let _: OrderStatus = OrderStatus::Active;
        let _: OrderStatus = OrderStatus::Filled;
        let _: OrderStatus = OrderStatus::Cancelled;
        let _: OrderStatus = OrderStatus::Expired;
    };
};

/// Compile-time assertion for Side enum uniqueness
const _SIDE_UNIQUENESS_CHECK: () = {
    let _ = || {
        let _: OrderSide = OrderSide::Buy;
        let _: OrderSide = OrderSide::Sell;
    };
};

/// Compile-time assertion for OrderType enum uniqueness
const _ORDER_TYPE_UNIQUENESS_CHECK: () = {
    let _ = || {
        let _: OrderType = OrderType::Market;
        let _: OrderType = OrderType::Limit;
        let _: OrderType = OrderType::Stop;
        let _: OrderType = OrderType::StopLimit;
        let _: OrderType = OrderType::Iceberg;
    };
};

/// Compile-time assertion for Symbol uniqueness
const _SYMBOL_UNIQUENESS_CHECK: () = {
    let _ = || {
        let _: Symbol = Symbol::new("TEST1".to_string());
        let _: Symbol = Symbol::from("TEST2");
        let _: Symbol = "BTC".into();
    };
};

/// Compile-time assertions for all UUID-based identifiers
const _ID_TYPES_UNIQUENESS_CHECK: () = {
    let _ = || {
        let _: OrderId = OrderId::new();
        let _: TradeId = TradeId::new();
        let _: FillId = FillId::new();
        let _: ClientId = ClientId::new();
        let _: AccountId = AccountId::new();
        let _: UserId = UserId::new();
        let _: EventId = EventId::new();
        let _: CorrelationId = CorrelationId::new();
        let _: CausationId = CausationId::new();
        let _: AggregateId = AggregateId::new();
    };
};

/// Compile-time documentation of type locations
pub const TYPE_LOCATIONS: &[(&str, &str)] = &[
    (Price", "types::basic"),
    (Quantity", "types::basic"),
    (Side", "types::basic"),
    (OrderType", "types::basic"),
    (OrderStatus", "types::basic"),
    (Symbol", "types::basic"),
    (OrderId", "types::basic"),
    (AccountId", "types::basic"),
    (UserId", "types::basic"),
    (PositionId", "types::basic"),
    (TradeId", "types::basic"),
    (AssetPair", "types::basic"),
    (Exchange", "types::basic"),
    (HftTimestamp", "types::basic"),
    (Balance", "types::basic"),
];

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

    #[test]
    fn test_price_operations() -> Result<(), Box<dyn std::error::Error>> {
        let price1 = Price::from_f64(123.45)?;
        let price2 = Price::from_f64(67.89)?;

        // Test basic operations
        let sum = price1 + price2;
        assert!(sum.to_f64() > 0.0);

        let diff = price1 - price2;
        assert!(diff.to_f64() > 0.0);

        Ok(())
    }

    #[test]
    fn test_quantity_operations() -> Result<(), Box<dyn std::error::Error>> {
        let qty1 = Quantity::from_f64(100.0)?;
        let qty2 = Quantity::from_f64(50.0)?;

        // Test basic operations
        let sum = qty1 + qty2;
        assert_eq!(sum.to_f64(), 150.0);

        let diff = qty1 - qty2;
    }

    #[test]
    fn test_order_creation() -> Result<(), Box<dyn std::error::Error>> {
        let symbol = Symbol::from("TEST1");
        let quantity = Quantity::from_f64(100.0)?;
        let price = Price::from_f64(150.0)?;

        let market_order = Order::market(symbol.clone(), OrderSide::Buy, quantity);
        assert_eq!(market_order.side, OrderSide::Buy);
        assert_eq!(market_order.order_type, OrderType::Market);

        let limit_order = Order::limit(symbol, OrderSide::Sell, quantity, price);
        assert_eq!(limit_order.side, OrderSide::Sell);
        assert_eq!(limit_order.order_type, OrderType::Limit);

        Ok(())
    }

    #[test]
    fn test_type_locations_completeness() {
        for (type_name, location) in TYPE_LOCATIONS {
            assert!(!type_name.is_empty());
            assert!(!location.is_empty());
        }

        // Verify no duplicate type names
        let mut type_names = HashSet::new();
        for (type_name, _) in TYPE_LOCATIONS {
            assert!(
                type_names.insert(type_name),
                "Duplicate type name: {}",
                type_name
            );
        }
    }
}
