//! Order execution unit tests
//! 
//! Tests order routing, execution algorithms, and venue selection
//! with focus on best execution and latency optimization.

// CANONICAL TYPE IMPORTS - Use types::prelude::Decimal
use std::collections::HashMap;
use std::time::{Duration, Instant};

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_smart_order_router_venue_selection() {
        let mut router = SmartOrderRouter::new();
        
        // Add venues with different characteristics
        router.add_venue(Venue {
            id: "NYSE".to_string(),
            latency: Duration::from_millis(2),
            fee_rate: Decimal::from_str("0.0005").unwrap(), // 0.05%
            liquidity_score: 95,
            reliability_score: 99,
        });
        
        router.add_venue(Venue {
            id: "NASDAQ".to_string(), 
            latency: Duration::from_millis(1),
            fee_rate: Decimal::from_str("0.0007").unwrap(), // 0.07%
            liquidity_score: 90,
            reliability_score: 98,
        });
        
        router.add_venue(Venue {
            id: "DARK_POOL".to_string(),
            latency: Duration::from_millis(5),
            fee_rate: Decimal::from_str("0.0002").unwrap(), // 0.02%
            liquidity_score: 70,
            reliability_score: 95,
        });
        
        // Small order - should prefer low latency
        let small_order = Order {
            id: OrderId::from("SMALL-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Market,
            quantity: Quantity::new(Decimal::from(100)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: None,
            time_in_force: TimeInForce::ImmediateOrCancel,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let small_routing = router.select_venue(&small_order, VenueSelectionStrategy::LatencyOptimized).await
            .expect("Should select venue for small order");
        assert_eq!(small_routing.venue_id, "NASDAQ"); // Lowest latency
        
        // Large order - should prefer liquidity
        let large_order = Order {
            id: OrderId::from("LARGE-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(10000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(150)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let large_routing = router.select_venue(&large_order, VenueSelectionStrategy::LiquidityOptimized).await
            .expect("Should select venue for large order");
        assert_eq!(large_routing.venue_id, "NYSE"); // Highest liquidity
    }
    
    #[tokio::test]
    async fn test_twap_execution_algorithm() {
        let mut twap = TwapExecutor::new(
            Duration::from_secs(300), // 5 minutes
            20 // 20 child orders
        );
        
        let parent_order = Order {
            id: OrderId::from("TWAP-PARENT"),
            symbol: Symbol::new("MSFT".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(10000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(300)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("INST-001".to_string()),
        };
        
        let execution_plan = twap.create_execution_plan(&parent_order).await
            .expect("Should create TWAP execution plan");
        
        // Should create 20 child orders
        assert_eq!(execution_plan.child_orders.len(), 20);
        
        // Each child order should be 500 shares (10000 / 20)
        for child_order in &execution_plan.child_orders {
            assert_eq!(child_order.quantity.value(), Decimal::from(500));
        }
        
        // Should have proper timing intervals (15 seconds each)
        let expected_interval = Duration::from_secs(15); // 300 seconds / 20 orders
        for i in 1..execution_plan.execution_schedule.len() {
            let interval = execution_plan.execution_schedule[i] - execution_plan.execution_schedule[i-1];
            let tolerance = Duration::from_millis(100);
            assert!((interval - expected_interval) < tolerance);
        }
    }
    
    #[tokio::test]
    async fn test_vwap_execution_algorithm() {
        let mut vwap = VwapExecutor::new();
        
        // Mock historical volume profile
        let volume_profile = vec![
            (chrono::NaiveTime::from_hms_opt(9, 30, 0).unwrap(), Decimal::from(1000)),  // Market open
            (chrono::NaiveTime::from_hms_opt(10, 0, 0).unwrap(), Decimal::from(800)),
            (chrono::NaiveTime::from_hms_opt(11, 0, 0).unwrap(), Decimal::from(600)),
            (chrono::NaiveTime::from_hms_opt(14, 0, 0).unwrap(), Decimal::from(700)),   // Lunch time
            (chrono::NaiveTime::from_hms_opt(15, 30, 0).unwrap(), Decimal::from(1200)), // Market close
        ];
        
        vwap.set_volume_profile(Symbol::new("GOOGL".to_string()).unwrap(), volume_profile);
        
        let parent_order = Order {
            id: OrderId::from("VWAP-PARENT"),
            symbol: Symbol::new("GOOGL".to_string()).unwrap(),
            side: Side::Sell,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(5000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(2500)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("FUND-001".to_string()),
        };
        
        let execution_plan = vwap.create_execution_plan(&parent_order).await
            .expect("Should create VWAP execution plan");
        
        // Should weight execution based on historical volume
        // Market open and close should have larger orders
        let open_order = execution_plan.child_orders.iter()
            .find(|o| o.id.value().contains("09:30"))
            .expect("Should have market open order");
        
        let close_order = execution_plan.child_orders.iter()
            .find(|o| o.id.value().contains("15:30"))
            .expect("Should have market close order");
        
        let midday_order = execution_plan.child_orders.iter()
            .find(|o| o.id.value().contains("11:00"))
            .expect("Should have midday order");
        
        // Open and close orders should be larger than midday
        assert!(open_order.quantity.value() > midday_order.quantity.value());
        assert!(close_order.quantity.value() > midday_order.quantity.value());
    }
    
    #[tokio::test]
    async fn test_implementation_shortfall_execution() {
        let mut is_executor = ImplementationShortfallExecutor::new(
            Decimal::from_str("0.02").unwrap(), // 2% risk aversion
            Duration::from_secs(1800) // 30 minutes
        );
        
        let parent_order = Order {
            id: OrderId::from("IS-PARENT"),
            symbol: Symbol::new("TSLA".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Market,
            quantity: Quantity::new(Decimal::from(2000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: None,
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("HEDGE-001".to_string()),
        };
        
        // Set market conditions
        let market_conditions = MarketConditions {
            volatility: Decimal::from_str("0.25").unwrap(), // 25% annualized
            spread: Decimal::from_str("0.10").unwrap(),    // $0.10 spread
            temporary_impact_rate: Decimal::from_str("0.001").unwrap(),
            permanent_impact_rate: Decimal::from_str("0.0005").unwrap(),
        };
        
        is_executor.set_market_conditions(market_conditions);
        
        let execution_plan = is_executor.create_execution_plan(&parent_order).await
            .expect("Should create IS execution plan");
        
        // Should optimize trade-off between market impact and timing risk
        assert!(!execution_plan.child_orders.is_empty());
        
        // In high volatility, should execute faster to reduce timing risk
        let total_execution_time = execution_plan.execution_schedule.last().unwrap() - 
                                 execution_plan.execution_schedule.first().unwrap();
        
        assert!(total_execution_time < Duration::from_secs(1800)); // Less than max time
        assert!(total_execution_time > Duration::from_secs(60));   // But not too fast
    }
    
    #[tokio::test]
    async fn test_iceberg_order_execution() {
        let mut iceberg = IcebergExecutor::new(
            Quantity::new(Decimal::from(500)).map_err(|e| format!("Failed to create iceberg quantity: {}", e)).unwrap(), // Show 500 shares at a time
            Decimal::from_str("0.01").unwrap() // 1% price improvement threshold
        );
        
        let parent_order = Order {
            id: OrderId::from("ICEBERG-PARENT"),
            symbol: Symbol::new("AMZN".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(5000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(3000)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let initial_slice = iceberg.get_initial_slice(&parent_order).await
            .expect("Should get initial iceberg slice");
        
        // Initial slice should be clip size
        assert_eq!(initial_slice.quantity.value(), Decimal::from(500));
        assert_eq!(initial_slice.price, parent_order.price);
        
        // Simulate partial fill
        let fill = Fill {
            id: FillId::new("FILL-ICE-001".to_string()),
            order_id: initial_slice.id.clone(),
            trade_id: TradeId::new("TRADE-ICE-001".to_string()),
            symbol: parent_order.symbol.clone(),
            side: parent_order.side,
            quantity: Quantity::new(Decimal::from(300)).map_err(|e| format!("Failed to create fill quantity: {}", e)).unwrap(),
            price: Price::new(Decimal::from(3000)).unwrap(),
            timestamp: chrono::Utc::now(),
            commission: None,
        };
        
        let next_slice = iceberg.handle_fill(&parent_order, &fill).await
            .expect("Should handle iceberg fill");
        
        assert!(next_slice.is_some());
        let next = next_slice.unwrap();
        
        // Should replenish to show full clip size again
        assert_eq!(next.quantity.value(), Decimal::from(500)); // 200 remaining + 300 new
    }
    
    #[tokio::test]
    async fn test_execution_quality_measurement() {
        let mut quality_tracker = ExecutionQualityTracker::new();
        
        // Record executions with different quality metrics
        let execution1 = ExecutionResult {
            order_id: OrderId::from("EXEC-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            expected_price: Price::new(Decimal::from(150)).unwrap(),
            executed_price: Price::new(Decimal::from_str("150.05").unwrap()).unwrap(),
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            execution_time: Duration::from_millis(50),
            venue: "NYSE".to_string(),
            timestamp: chrono::Utc::now(),
        };
        
        let execution2 = ExecutionResult {
            order_id: OrderId::from("EXEC-002"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            expected_price: Price::new(Decimal::from(150)).unwrap(),
            executed_price: Price::new(Decimal::from_str("149.98").unwrap()).unwrap(),
            quantity: Quantity::new(Decimal::from(500)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            execution_time: Duration::from_millis(25),
            venue: "NASDAQ".to_string(),
            timestamp: chrono::Utc::now(),
        };
        
        quality_tracker.record_execution(execution1);
        quality_tracker.record_execution(execution2);
        
        let quality_metrics = quality_tracker.calculate_metrics(Duration::from_secs(3600)).await
            .expect("Should calculate quality metrics");
        
        // Should calculate average slippage
        let expected_avg_slippage = (Decimal::from_str("0.05").unwrap() + Decimal::from_str("-0.02").unwrap()) / Decimal::from(2);
        assert_eq!(quality_metrics.average_slippage, expected_avg_slippage);
        
        // Should track fill rates and timing
        assert_eq!(quality_metrics.total_executions, 2);
        assert!(quality_metrics.average_execution_time < Duration::from_millis(50));
    }
    
    #[tokio::test]
    async fn test_multi_venue_execution() {
        let mut multi_venue = MultiVenueExecutor::new();
        
        multi_venue.add_venue("NYSE", 0.3);    // 30% allocation
        multi_venue.add_venue("NASDAQ", 0.4);  // 40% allocation
        multi_venue.add_venue("BATS", 0.2);    // 20% allocation
        multi_venue.add_venue("IEX", 0.1);     // 10% allocation
        
        let large_order = Order {
            id: OrderId::from("MULTI-VENUE"),
            symbol: Symbol::new("SPY".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(10000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(400)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("INSTITUTION".to_string()),
        };
        
        let venue_orders = multi_venue.split_order(&large_order).await
            .expect("Should split order across venues");
        
        assert_eq!(venue_orders.len(), 4);
        
        // Check allocations
        let nyse_order = venue_orders.iter().find(|o| o.venue_id == "NYSE").unwrap();
        let nasdaq_order = venue_orders.iter().find(|o| o.venue_id == "NASDAQ").unwrap();
        let bats_order = venue_orders.iter().find(|o| o.venue_id == "BATS").unwrap();
        let iex_order = venue_orders.iter().find(|o| o.venue_id == "IEX").unwrap();
        
        assert_eq!(nyse_order.quantity.value(), Decimal::from(3000));   // 30%
        assert_eq!(nasdaq_order.quantity.value(), Decimal::from(4000)); // 40%
        assert_eq!(bats_order.quantity.value(), Decimal::from(2000));   // 20%
        assert_eq!(iex_order.quantity.value(), Decimal::from(1000));    // 10%
        
        // Total should match original order
        let total_quantity: Decimal = venue_orders.iter()
            .map(|o| o.quantity.value())
            .sum();
        assert_eq!(total_quantity, large_order.quantity.value());
    }
    
    #[tokio::test]
    async fn test_latency_measurement() {
        let mut latency_tracker = LatencyTracker::new();
        
        let start_time = Instant::now();
        
        // Simulate order lifecycle with timing points
        let order_id = OrderId::from("LATENCY-TEST");
        
        latency_tracker.mark_order_sent(&order_id, start_time);
        
        let ack_time = start_time + Duration::from_micros(500); // 500μs to ack
        latency_tracker.mark_order_ack(&order_id, ack_time);
        
        let fill_time = start_time + Duration::from_millis(2); // 2ms to fill
        latency_tracker.mark_order_fill(&order_id, fill_time);
        
        let metrics = latency_tracker.get_metrics(&order_id).await
            .expect("Should get latency metrics");
        
        assert_eq!(metrics.order_to_ack, Duration::from_micros(500));
        assert_eq!(metrics.order_to_fill, Duration::from_millis(2));
        assert_eq!(metrics.ack_to_fill, Duration::from_millis(2) - Duration::from_micros(500));
    }
}

// Production implementations for testing
#[derive(Debug, Clone)]
struct Venue {
    id: String,
    latency: Duration,
    fee_rate: Decimal,
    liquidity_score: u32,
    reliability_score: u32,
}

#[derive(Debug)]
struct SmartOrderRouter {
    venues: Vec<Venue>,
}

#[derive(Debug)]
enum VenueSelectionStrategy {
    LatencyOptimized,
    LiquidityOptimized,
    CostOptimized,
    Balanced,
}

#[derive(Debug)]
struct VenueRoutingDecision {
    venue_id: String,
    expected_latency: Duration,
    expected_fee: Money,
    confidence_score: u32,
}

impl SmartOrderRouter {
    fn new() -> Self {
        Self {
            venues: Vec::new(),
        }
    }
    
    fn add_venue(&mut self, venue: Venue) {
        self.venues.push(venue);
    }
    
    async fn select_venue(&self, order: &Order, strategy: VenueSelectionStrategy) -> Result<VenueRoutingDecision, Box<dyn std::error::Error>> {
        if self.venues.is_empty() {
            return Err("No venues available".into());
        }
        
        let best_venue = match strategy {
            VenueSelectionStrategy::LatencyOptimized => {
                self.venues.iter().min_by_key(|v| v.latency).unwrap()
            },
            VenueSelectionStrategy::LiquidityOptimized => {
                self.venues.iter().max_by_key(|v| v.liquidity_score).unwrap()
            },
            VenueSelectionStrategy::CostOptimized => {
                self.venues.iter().min_by_key(|v| v.fee_rate).unwrap()
            },
            VenueSelectionStrategy::Balanced => {
                // Simple scoring: combine latency, liquidity, and cost
                self.venues.iter().max_by_key(|v| {
                    let latency_score = 100 - (v.latency.as_millis() as u32);
                    let cost_score = 100 - (v.fee_rate * Decimal::from(10000)).to_u32().unwrap_or(0);
                    latency_score + v.liquidity_score + cost_score + v.reliability_score
                }).unwrap()
            }
        };
        
        let order_value = order.quantity.value() * 
            order.price.as_ref().unwrap_or(&Price::new(Decimal::from(100)).unwrap()).value();
        
        Ok(VenueRoutingDecision {
            venue_id: best_venue.id.clone(),
            expected_latency: best_venue.latency,
            expected_fee: Money::new(order_value * best_venue.fee_rate, Currency::USD),
            confidence_score: best_venue.reliability_score,
        })
    }
}

#[derive(Debug)]
struct TwapExecutor {
    duration: Duration,
    num_slices: usize,
}

#[derive(Debug)]
struct ExecutionPlan {
    child_orders: Vec<Order>,
    execution_schedule: Vec<chrono::DateTime<chrono::Utc>>,
}

impl TwapExecutor {
    fn new(duration: Duration, num_slices: usize) -> Self {
        Self { duration, num_slices }
    }
    
    async fn create_execution_plan(&self, parent_order: &Order) -> Result<ExecutionPlan, Box<dyn std::error::Error>> {
        let slice_size = parent_order.quantity.value() / Decimal::from(self.num_slices);
        let slice_interval = self.duration / self.num_slices as u32;
        
        let mut child_orders = Vec::new();
        let mut execution_schedule = Vec::new();
        
        let start_time = chrono::Utc::now();
        
        for i in 0..self.num_slices {
            let child_order = Order {
                id: OrderId::new(format!("{}-TWAP-{}", parent_order.id.value(), i)),
                symbol: parent_order.symbol.clone(),
                side: parent_order.side,
                order_type: parent_order.order_type,
                quantity: Quantity::new(slice_size).map_err(|e| format!("Failed to create slice quantity: {}", e)).unwrap(),
                price: parent_order.price.clone(),
                time_in_force: TimeInForce::ImmediateOrCancel,
                timestamp: parent_order.timestamp,
                status: OrderStatus::New,
                client_id: parent_order.client_id.clone(),
            };
            
            child_orders.push(child_order);
            execution_schedule.push(start_time + chrono::Duration::from_std(slice_interval * i as u32).unwrap());
        }
        
        Ok(ExecutionPlan {
            child_orders,
            execution_schedule,
        })
    }
}

#[derive(Debug)]
struct VwapExecutor {
    volume_profiles: HashMap<Symbol, Vec<(chrono::NaiveTime, Decimal)>>,
}

impl VwapExecutor {
    fn new() -> Self {
        Self {
            volume_profiles: HashMap::new(),
        }
    }
    
    fn set_volume_profile(&mut self, symbol: Symbol, profile: Vec<(chrono::NaiveTime, Decimal)>) {
        self.volume_profiles.insert(symbol, profile);
    }
    
    async fn create_execution_plan(&self, parent_order: &Order) -> Result<ExecutionPlan, Box<dyn std::error::Error>> {
        let profile = self.volume_profiles.get(&parent_order.symbol)
            .ok_or("No volume profile for symbol")?;
        
        let total_volume: Decimal = profile.iter().map(|(_, vol)| *vol).sum();
        
        let mut child_orders = Vec::new();
        let mut execution_schedule = Vec::new();
        
        let base_date = chrono::Utc::now().date_naive();
        
        for (time, historical_volume) in profile {
            let weight = historical_volume / total_volume;
            let slice_quantity = parent_order.quantity.value() * weight;
            
            if slice_quantity > Decimal::ZERO {
                let child_order = Order {
                    id: OrderId::new(format!("{}-VWAP-{}", parent_order.id.value(), time.format("%H:%M"))),
                    symbol: parent_order.symbol.clone(),
                    side: parent_order.side,
                    order_type: parent_order.order_type,
                    quantity: Quantity::new(slice_quantity).map_err(|e| format!("Failed to create slice quantity: {}", e)).unwrap(),
                    price: parent_order.price.clone(),
                    time_in_force: TimeInForce::ImmediateOrCancel,
                    timestamp: parent_order.timestamp,
                    status: OrderStatus::New,
                    client_id: parent_order.client_id.clone(),
                };
                
                child_orders.push(child_order);
                
                let execution_time = chrono::DateTime::from_naive_utc_and_offset(
                    base_date.and_time(*time),
                    chrono::Utc
                );
                execution_schedule.push(execution_time);
            }
        }
        
        Ok(ExecutionPlan {
            child_orders,
            execution_schedule,
        })
    }
}

#[derive(Debug)]
struct ImplementationShortfallExecutor {
    risk_aversion: Decimal,
    max_duration: Duration,
}

#[derive(Debug)]
struct MarketConditions {
    volatility: Decimal,
    spread: Decimal,
    temporary_impact_rate: Decimal,
    permanent_impact_rate: Decimal,
}

impl ImplementationShortfallExecutor {
    fn new(risk_aversion: Decimal, max_duration: Duration) -> Self {
        Self { risk_aversion, max_duration }
    }
    
    fn set_market_conditions(&mut self, _conditions: MarketConditions) {
        // Store market conditions for optimization
    }
    
    async fn create_execution_plan(&self, parent_order: &Order) -> Result<ExecutionPlan, Box<dyn std::error::Error>> {
        // Simplified IS optimization - in practice would solve for optimal trajectory
        let num_slices = if parent_order.quantity.value() > Decimal::from(5000) { 10 } else { 5 };
        let execution_duration = self.max_duration / 2; // Execute faster in volatile markets
        
        let slice_size = parent_order.quantity.value() / Decimal::from(num_slices);
        let slice_interval = execution_duration / num_slices as u32;
        
        let mut child_orders = Vec::new();
        let mut execution_schedule = Vec::new();
        
        let start_time = chrono::Utc::now();
        
        for i in 0..num_slices {
            let child_order = Order {
                id: OrderId::new(format!("{}-IS-{}", parent_order.id.value(), i)),
                symbol: parent_order.symbol.clone(),
                side: parent_order.side,
                order_type: OrderType::Limit, // Use limit orders for better control
                quantity: Quantity::new(slice_size).map_err(|e| format!("Failed to create slice quantity: {}", e)).unwrap(),
                price: parent_order.price.clone(),
                time_in_force: TimeInForce::ImmediateOrCancel,
                timestamp: parent_order.timestamp,
                status: OrderStatus::New,
                client_id: parent_order.client_id.clone(),
            };
            
            child_orders.push(child_order);
            execution_schedule.push(start_time + chrono::Duration::from_std(slice_interval * i as u32).unwrap());
        }
        
        Ok(ExecutionPlan {
            child_orders,
            execution_schedule,
        })
    }
}

#[derive(Debug)]
struct IcebergExecutor {
    clip_size: Quantity,
    price_improvement_threshold: Decimal,
}

impl IcebergExecutor {
    fn new(clip_size: Quantity, price_improvement_threshold: Decimal) -> Self {
        Self { clip_size, price_improvement_threshold }
    }
    
    async fn get_initial_slice(&self, parent_order: &Order) -> Result<Order, Box<dyn std::error::Error>> {
        let slice_quantity = std::cmp::min(parent_order.quantity.value(), self.clip_size.value());
        
        Ok(Order {
            id: OrderId::new(format!("{}-ICE-0", parent_order.id.value())),
            symbol: parent_order.symbol.clone(),
            side: parent_order.side,
            order_type: parent_order.order_type,
            quantity: Quantity::new(slice_quantity).map_err(|e| format!("Failed to create slice quantity: {}", e)).unwrap(),
            price: parent_order.price.clone(),
            time_in_force: TimeInForce::Day,
            timestamp: parent_order.timestamp,
            status: OrderStatus::New,
            client_id: parent_order.client_id.clone(),
        })
    }
    
    async fn handle_fill(&self, parent_order: &Order, _fill: &Fill) -> Result<Option<Order>, Box<dyn std::error::Error>> {
        // Replenish the visible quantity
        Ok(Some(Order {
            id: OrderId::new(format!("{}-ICE-REFILL", parent_order.id.value())),
            symbol: parent_order.symbol.clone(),
            side: parent_order.side,
            order_type: parent_order.order_type,
            quantity: self.clip_size.clone(),
            price: parent_order.price.clone(),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: parent_order.client_id.clone(),
        }))
    }
}

#[derive(Debug)]
struct ExecutionResult {
    order_id: OrderId,
    symbol: Symbol,
    expected_price: Price,
    executed_price: Price,
    quantity: Quantity,
    execution_time: Duration,
    venue: String,
    timestamp: chrono::DateTime<chrono::Utc>,
}

#[derive(Debug)]
struct ExecutionQualityMetrics {
    average_slippage: Decimal,
    total_executions: usize,
    average_execution_time: Duration,
    fill_rate: Decimal,
    venue_performance: HashMap<String, VenueMetrics>,
}

#[derive(Debug)]
struct VenueMetrics {
    average_slippage: Decimal,
    execution_count: usize,
    average_latency: Duration,
}

#[derive(Debug)]
struct ExecutionQualityTracker {
    executions: Vec<ExecutionResult>,
}

impl ExecutionQualityTracker {
    fn new() -> Self {
        Self {
            executions: Vec::new(),
        }
    }
    
    fn record_execution(&mut self, execution: ExecutionResult) {
        self.executions.push(execution);
    }
    
    async fn calculate_metrics(&self, period: Duration) -> Result<ExecutionQualityMetrics, Box<dyn std::error::Error>> {
        let cutoff_time = chrono::Utc::now() - chrono::Duration::from_std(period).unwrap();
        let recent_executions: Vec<_> = self.executions.iter()
            .filter(|e| e.timestamp > cutoff_time)
            .collect();
        
        if recent_executions.is_empty() {
            return Err("No executions in specified period".into());
        }
        
        // Calculate average slippage
        let total_slippage: Decimal = recent_executions.iter()
            .map(|e| e.executed_price.value() - e.expected_price.value())
            .sum();
        let average_slippage = total_slippage / Decimal::from(recent_executions.len());
        
        // Calculate average execution time
        let total_time: Duration = recent_executions.iter()
            .map(|e| e.execution_time)
            .sum();
        let average_execution_time = total_time / recent_executions.len() as u32;
        
        // Build venue performance map
        let mut venue_performance = HashMap::new();
        let mut venue_groups: HashMap<String, Vec<&ExecutionResult>> = HashMap::new();
        
        for exec in &recent_executions {
            venue_groups.entry(exec.venue.clone()).or_default().push(exec);
        }
        
        for (venue, execs) in venue_groups {
            let venue_slippage: Decimal = execs.iter()
                .map(|e| e.executed_price.value() - e.expected_price.value())
                .sum::<Decimal>() / Decimal::from(execs.len());
            
            let venue_latency = execs.iter()
                .map(|e| e.execution_time)
                .sum::<Duration>() / execs.len() as u32;
            
            venue_performance.insert(venue, VenueMetrics {
                average_slippage: venue_slippage,
                execution_count: execs.len(),
                average_latency: venue_latency,
            });
        }
        
        Ok(ExecutionQualityMetrics {
            average_slippage,
            total_executions: recent_executions.len(),
            average_execution_time,
            fill_rate: Decimal::ONE, // Simplified - assume all filled
            venue_performance,
        })
    }
}

#[derive(Debug)]
struct MultiVenueExecutor {
    venue_allocations: HashMap<String, f64>,
}

#[derive(Debug)]
struct VenueOrder {
    venue_id: String,
    order: Order,
    quantity: Quantity,
}

impl MultiVenueExecutor {
    fn new() -> Self {
        Self {
            venue_allocations: HashMap::new(),
        }
    }
    
    fn add_venue(&mut self, venue_id: &str, allocation: f64) {
        self.venue_allocations.insert(venue_id.to_string(), allocation);
    }
    
    async fn split_order(&self, parent_order: &Order) -> Result<Vec<VenueOrder>, Box<dyn std::error::Error>> {
        let mut venue_orders = Vec::new();
        
        for (venue_id, &allocation) in &self.venue_allocations {
            let venue_quantity = parent_order.quantity.value() * Decimal::try_from(allocation).map_err(|e| format!("Failed to convert allocation to Decimal: {}", e)).unwrap();
            
            if venue_quantity > Decimal::ZERO {
                let venue_order = Order {
                    id: OrderId::new(format!("{}-{}", parent_order.id.value(), venue_id)),
                    symbol: parent_order.symbol.clone(),
                    side: parent_order.side,
                    order_type: parent_order.order_type,
                    quantity: Quantity::new(venue_quantity).map_err(|e| format!("Failed to create venue quantity: {}", e)).unwrap(),
                    price: parent_order.price.clone(),
                    time_in_force: parent_order.time_in_force,
                    timestamp: parent_order.timestamp,
                    status: OrderStatus::New,
                    client_id: parent_order.client_id.clone(),
                };
                
                venue_orders.push(VenueOrder {
                    venue_id: venue_id.clone(),
                    order: venue_order,
                    quantity: Quantity::new(venue_quantity).map_err(|e| format!("Failed to create venue quantity: {}", e)).unwrap(),
                });
            }
        }
        
        Ok(venue_orders)
    }
}

#[derive(Debug)]
struct LatencyMetrics {
    order_to_ack: Duration,
    order_to_fill: Duration,
    ack_to_fill: Duration,
}

#[derive(Debug)]
struct LatencyTracker {
    timing_points: HashMap<OrderId, TimingPoints>,
}

#[derive(Debug)]
struct TimingPoints {
    order_sent: Instant,
    order_ack: Option<Instant>,
    order_fill: Option<Instant>,
}

impl LatencyTracker {
    fn new() -> Self {
        Self {
            timing_points: HashMap::new(),
        }
    }
    
    fn mark_order_sent(&mut self, order_id: &OrderId, time: Instant) {
        self.timing_points.insert(order_id.clone(), TimingPoints {
            order_sent: time,
            order_ack: None,
            order_fill: None,
        });
    }
    
    fn mark_order_ack(&mut self, order_id: &OrderId, time: Instant) {
        if let Some(points) = self.timing_points.get_mut(order_id) {
            points.order_ack = Some(time);
        }
    }
    
    fn mark_order_fill(&mut self, order_id: &OrderId, time: Instant) {
        if let Some(points) = self.timing_points.get_mut(order_id) {
            points.order_fill = Some(time);
        }
    }
    
    async fn get_metrics(&self, order_id: &OrderId) -> Result<LatencyMetrics, Box<dyn std::error::Error>> {
        let points = self.timing_points.get(order_id)
            .ok_or("Order not found in timing points")?;
        
        let order_to_ack = points.order_ack
            .ok_or("Order acknowledgment not recorded")?
            .duration_since(points.order_sent);
        
        let order_to_fill = points.order_fill
            .ok_or("Order fill not recorded")?
            .duration_since(points.order_sent);
        
        let ack_to_fill = points.order_fill.unwrap()
            .duration_since(points.order_ack.unwrap());
        
        Ok(LatencyMetrics {
            order_to_ack,
            order_to_fill,
            ack_to_fill,
        })
    }
}