//! Order Manager
//!
//! Handles order lifecycle management, tracking, and validation

use chrono::{Duration, Utc};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, info};

use crate::trading_operations::{ExecutionResult, TradingOrder};
use common::{OrderId, OrderStatus, OrderType};
use rust_decimal::Decimal;

/// Order Manager for tracking and managing orders
#[derive(Debug)]
/// OrderManager
///
/// Auto-generated documentation placeholder - enhance with specifics
pub struct OrderManager {
    /// Active orders storage
    orders: Arc<RwLock<HashMap<OrderId, TradingOrder>>>,
}

impl OrderManager {
    /// Create a new order manager
    pub fn new() -> Self {
        Self {
            orders: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Validate an order before submission
    pub async fn validate_order(&self, order: &TradingOrder) -> Result<(), String> {
        // Basic validation checks
        if order.quantity <= Decimal::ZERO {
            return Err("Invalid quantity: must be positive".to_owned());
        }

        if order.price <= Decimal::ZERO && matches!(order.order_type, OrderType::Limit) {
            return Err("Invalid price: must be positive for limit orders".to_owned());
        }

        if order.symbol.is_empty() {
            return Err("Invalid symbol: cannot be empty".to_owned());
        }

        // Check for duplicate order IDs
        let orders = self.orders.read().await;
        if orders.contains_key(&order.id) {
            return Err("Order ID already exists".to_owned());
        }

        debug!("Order validation passed for {}", order.id);
        Ok(())
    }

    /// Validate and add order atomically (prevents duplicate order race condition).
    ///
    /// Unlike the separate `validate_order` + `add_order` pair, this method holds
    /// a single write lock for the entire operation, preventing a TOCTOU race where
    /// two orders with the same ID both pass validation concurrently.
    pub async fn validate_and_add_order(&self, order: TradingOrder) -> Result<(), String> {
        let mut orders = self.orders.write().await;

        // Duplicate check under write lock
        if orders.contains_key(&order.id) {
            return Err(format!("Duplicate order ID: {}", order.id));
        }

        // Validate order fields (same checks as validate_order)
        if order.quantity <= Decimal::ZERO {
            return Err("Invalid quantity: must be positive".to_owned());
        }

        if order.price <= Decimal::ZERO && matches!(order.order_type, OrderType::Limit) {
            return Err("Invalid price: must be positive for limit orders".to_owned());
        }

        if order.symbol.is_empty() {
            return Err("Invalid symbol: cannot be empty".to_owned());
        }

        debug!("Order validation passed for {}, adding to tracking", order.id);
        orders.insert(order.id, order);
        Ok(())
    }

    /// Add a new order to tracking
    pub async fn add_order(&self, order: TradingOrder) {
        let mut orders = self.orders.write().await;
        info!("Adding order {} to tracking", order.id);
        orders.insert(order.id, order);
    }

    /// Get an order by ID
    pub async fn get_order(&self, order_id: &OrderId) -> Option<TradingOrder> {
        let orders = self.orders.read().await;
        orders.get(order_id).cloned()
    }

    /// Update order status
    pub async fn update_order_status(
        &self,
        order_id: &OrderId,
        status: OrderStatus,
    ) -> Result<(), String> {
        let mut orders = self.orders.write().await;

        if let Some(order) = orders.get_mut(order_id) {
            let old_status = order.status;
            order.status = status;
            // Updated timestamp would be tracked here
            // order.updated_at = Utc::now();

            info!(
                "Order {} status updated: {:?} -> {:?}",
                order_id, old_status, order.status
            );
            Ok(())
        } else {
            Err("Order not found".to_owned())
        }
    }

    /// Process an execution and update the order
    pub async fn process_execution(&self, execution: &ExecutionResult) -> Result<(), String> {
        let mut orders = self.orders.write().await;

        if let Some(order) = orders.get_mut(&execution.order_id) {
            // Reject fills on already-filled orders
            if order.status == OrderStatus::Filled {
                return Err(format!("Order {} already fully filled", execution.order_id));
            }

            // Check for overfill
            let new_fill = order.fill_quantity + execution.executed_quantity;
            if new_fill > order.quantity {
                return Err(format!(
                    "Overfill rejected: {} + {} = {} > order qty {}",
                    order.fill_quantity, execution.executed_quantity, new_fill, order.quantity
                ));
            }

            // Update fill information with capped value
            order.fill_quantity = new_fill;
            order.executed_at = Some(execution.execution_time);

            // Calculate weighted average fill price
            if let Some(avg_price) = order.average_fill_price {
                let previous_fill = order.fill_quantity - execution.executed_quantity;
                let total_value = avg_price * previous_fill
                    + execution.execution_price * execution.executed_quantity;
                order.average_fill_price = Some(total_value / order.fill_quantity);
            } else {
                order.average_fill_price = Some(execution.execution_price);
            }

            // Update order status based on fill
            if order.fill_quantity >= order.quantity {
                order.status = OrderStatus::Filled;
                info!("Order {} fully filled", execution.order_id);
            } else {
                order.status = OrderStatus::PartiallyFilled;
                info!(
                    "Order {} partially filled: {}/{}",
                    execution.order_id, order.fill_quantity, order.quantity
                );
            }

            Ok(())
        } else {
            Err("Order not found for execution".to_owned())
        }
    }

    /// Get all orders with optional status filter
    pub async fn get_orders(&self, status_filter: Option<OrderStatus>) -> Vec<TradingOrder> {
        let orders = self.orders.read().await;

        orders
            .values()
            .filter(|order| {
                if let Some(ref status) = status_filter {
                    order.status == *status
                } else {
                    true
                }
            })
            .cloned()
            .collect()
    }

    /// Get open orders (submitted or partially filled)
    pub async fn get_open_orders(&self) -> Vec<TradingOrder> {
        let orders = self.orders.read().await;

        orders
            .values()
            .filter(|order| {
                matches!(
                    order.status,
                    OrderStatus::Submitted | OrderStatus::PartiallyFilled
                )
            })
            .cloned()
            .collect()
    }

    /// Cancel an order
    pub async fn cancel_order(&self, order_id: &OrderId) -> Result<(), String> {
        self.update_order_status(order_id, OrderStatus::Cancelled)
            .await
    }

    /// Remove old completed orders (cleanup)
    pub async fn cleanup_old_orders(&self, max_age_hours: i64) {
        let mut orders = self.orders.write().await;
        let cutoff_time = Utc::now() - Duration::hours(max_age_hours);

        orders.retain(|_, order| {
            let keep = match order.status {
                OrderStatus::Filled | OrderStatus::Cancelled | OrderStatus::Rejected => {
                    order.created_at > cutoff_time
                },
                OrderStatus::Created
                | OrderStatus::Submitted
                | OrderStatus::PartiallyFilled
                | OrderStatus::New
                | OrderStatus::Expired
                | OrderStatus::Pending
                | OrderStatus::Working
                | OrderStatus::Unknown
                | OrderStatus::Suspended
                | OrderStatus::PendingCancel
                | OrderStatus::PendingReplace
                | _ => true, // Keep active orders
            };

            if !keep {
                debug!("Removing old order {} from tracking", order.id);
            }

            keep
        });
    }

    /// Get order statistics
    pub async fn get_order_stats(&self) -> OrderManagerStats {
        let orders = self.orders.read().await;

        let mut stats = OrderManagerStats::default();

        for order in orders.values() {
            stats.total_orders += 1;

            match order.status {
                OrderStatus::Submitted => stats.submitted_orders += 1,
                OrderStatus::PartiallyFilled => stats.partially_filled_orders += 1,
                OrderStatus::Filled => stats.filled_orders += 1,
                OrderStatus::Cancelled => stats.cancelled_orders += 1,
                OrderStatus::Rejected => stats.rejected_orders += 1,
                OrderStatus::Created
                | OrderStatus::New
                | OrderStatus::Expired
                | OrderStatus::Pending
                | OrderStatus::Working
                | OrderStatus::Unknown
                | OrderStatus::Suspended
                | OrderStatus::PendingCancel
                | OrderStatus::PendingReplace
                | _ => {},
            }
        }

        stats.fill_rate = if stats.total_orders > 0 {
            (stats.filled_orders + stats.partially_filled_orders) as f64 / stats.total_orders as f64
        } else {
            0.0
        };

        stats
    }
}

impl Default for OrderManager {
    fn default() -> Self {
        Self::new()
    }
}

/// Order manager statistics
#[derive(Debug, Default)]
/// OrderManagerStats
///
/// Auto-generated documentation placeholder - enhance with specifics
pub struct OrderManagerStats {
    /// Total Orders
    pub total_orders: u32,
    /// Submitted Orders
    pub submitted_orders: u32,
    /// Partially Filled Orders
    pub partially_filled_orders: u32,
    /// Filled Orders
    pub filled_orders: u32,
    /// Cancelled Orders
    pub cancelled_orders: u32,
    /// Rejected Orders
    pub rejected_orders: u32,
    /// Fill Rate
    pub fill_rate: f64,
}

#[cfg(test)]
#[allow(clippy::assertions_on_result_states)]
mod tests {
    use super::*;
    use common::{OrderSide, OrderType, TimeInForce};

    fn create_test_order(id: &str, symbol: &str, quantity: i64, price: i64) -> TradingOrder {
        TradingOrder {
            id: id.to_string().into(),
            symbol: symbol.to_string(),
            side: OrderSide::Buy,
            order_type: OrderType::Limit,
            quantity: Decimal::from(quantity),
            price: Decimal::from(price),
            time_in_force: TimeInForce::GoodTillCancel,
            account_id: None,
            metadata: HashMap::new(),
            created_at: Utc::now(),
            submitted_at: None,
            executed_at: None,
            status: OrderStatus::Created,
            fill_quantity: Decimal::ZERO,
            average_fill_price: None,
        }
    }

    #[tokio::test]
    async fn test_order_manager_validation() {
        let manager = OrderManager::new();

        let valid_order = create_test_order("test-001", "BTCUSD", 100, 50000);

        let result = manager.validate_order(&valid_order).await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_order_validation_negative_quantity() {
        let manager = OrderManager::new();

        let mut invalid_order = create_test_order("test-neg-qty", "BTCUSD", 100, 50000);
        invalid_order.quantity = Decimal::from(-10);

        let result = manager.validate_order(&invalid_order).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("positive"));
    }

    #[tokio::test]
    async fn test_order_validation_zero_quantity() {
        let manager = OrderManager::new();

        let mut invalid_order = create_test_order("test-zero-qty", "BTCUSD", 100, 50000);
        invalid_order.quantity = Decimal::ZERO;

        let result = manager.validate_order(&invalid_order).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("positive"));
    }

    #[tokio::test]
    async fn test_order_validation_invalid_limit_price() {
        let manager = OrderManager::new();

        let mut invalid_order = create_test_order("test-bad-price", "BTCUSD", 100, 50000);
        invalid_order.order_type = OrderType::Limit;
        invalid_order.price = Decimal::from(-100);

        let result = manager.validate_order(&invalid_order).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("price"));
    }

    #[tokio::test]
    async fn test_order_validation_empty_symbol() {
        let manager = OrderManager::new();

        let mut invalid_order = create_test_order("test-empty-sym", "BTCUSD", 100, 50000);
        invalid_order.symbol = String::new();

        let result = manager.validate_order(&invalid_order).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("symbol"));
    }

    #[tokio::test]
    async fn test_order_validation_duplicate_id() {
        let manager = OrderManager::new();

        let order1 = create_test_order("test-dup", "BTCUSD", 100, 50000);
        let order1_id = order1.id;
        manager.add_order(order1.clone()).await;

        // Create order2 with same ID as order1
        let mut order2 = create_test_order("test-dup-2", "ETHUSD", 50, 3000);
        order2.id = order1_id; // Use same ID to trigger duplicate check
        let result = manager.validate_order(&order2).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("already exists"));
    }

    #[tokio::test]
    async fn test_order_tracking() {
        let manager = OrderManager::new();

        let order = TradingOrder {
            id: "test-002".to_string().into(),
            symbol: "ETHUSD".to_string(),
            side: OrderSide::Sell,
            order_type: OrderType::Market,
            quantity: Decimal::from(10),
            price: Decimal::from(3000),
            time_in_force: TimeInForce::ImmediateOrCancel,
            account_id: None,
            metadata: HashMap::new(),
            created_at: Utc::now(),
            submitted_at: None,
            executed_at: None,
            status: OrderStatus::Created,
            fill_quantity: Decimal::ZERO,
            average_fill_price: None,
        };

        manager.add_order(order.clone()).await;

        let retrieved = manager.get_order(&order.id).await;
        assert!(retrieved.is_some());
        assert_eq!(
            retrieved.expect("Order should exist after adding").id,
            order.id
        );
    }

    #[tokio::test]
    async fn test_order_status_transitions() {
        let manager = OrderManager::new();

        let order = create_test_order("test-status", "BTCUSD", 100, 50000);
        manager.add_order(order.clone()).await;

        // Test transition to Submitted
        let result = manager
            .update_order_status(&order.id, OrderStatus::Submitted)
            .await;
        assert!(result.is_ok());
        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.status, OrderStatus::Submitted);

        // Test transition to PartiallyFilled
        let result = manager
            .update_order_status(&order.id, OrderStatus::PartiallyFilled)
            .await;
        assert!(result.is_ok());
        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.status, OrderStatus::PartiallyFilled);

        // Test transition to Filled
        let result = manager
            .update_order_status(&order.id, OrderStatus::Filled)
            .await;
        assert!(result.is_ok());
        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.status, OrderStatus::Filled);
    }

    #[tokio::test]
    async fn test_order_status_update_not_found() {
        let manager = OrderManager::new();

        let result = manager
            .update_order_status(&"nonexistent".to_string().into(), OrderStatus::Filled)
            .await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("not found"));
    }

    #[tokio::test]
    async fn test_partial_execution() {
        let manager = OrderManager::new();

        let mut order = create_test_order("test-partial", "BTCUSD", 100, 50000);
        order.status = OrderStatus::Submitted;
        manager.add_order(order.clone()).await;

        // First partial fill
        let execution1 = ExecutionResult {
            order_id: order.id.clone(),
            symbol: "BTCUSD".to_string(),
            side: common::OrderSide::Buy,
            executed_quantity: Decimal::from(30),
            execution_price: Decimal::from(50000),
            execution_time: Utc::now(),
            commission: Decimal::from(10),
            liquidity_flag: crate::trading_operations::LiquidityFlag::Maker,
        };

        let result = manager.process_execution(&execution1).await;
        assert!(result.is_ok());

        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.fill_quantity, Decimal::from(30));
        assert_eq!(updated.status, OrderStatus::PartiallyFilled);
        assert_eq!(updated.average_fill_price, Some(Decimal::from(50000)));

        // Second partial fill at different price
        let execution2 = ExecutionResult {
            order_id: order.id.clone(),
            symbol: "BTCUSD".to_string(),
            side: common::OrderSide::Buy,
            executed_quantity: Decimal::from(70),
            execution_price: Decimal::from(50100),
            execution_time: Utc::now(),
            commission: Decimal::from(20),
            liquidity_flag: crate::trading_operations::LiquidityFlag::Taker,
        };

        let result = manager.process_execution(&execution2).await;
        assert!(result.is_ok());

        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.fill_quantity, Decimal::from(100));
        assert_eq!(updated.status, OrderStatus::Filled);

        // Verify weighted average price: (30 * 50000 + 70 * 50100) / 100 = 50070
        let expected_avg = Decimal::from(50070);
        assert_eq!(updated.average_fill_price, Some(expected_avg));
    }

    #[tokio::test]
    async fn test_get_open_orders() {
        let manager = OrderManager::new();

        let mut order1 = create_test_order("test-open-1", "BTCUSD", 100, 50000);
        order1.status = OrderStatus::Submitted;
        let order1_id = order1.id;
        manager.add_order(order1).await;

        let mut order2 = create_test_order("test-open-2", "ETHUSD", 50, 3000);
        order2.status = OrderStatus::PartiallyFilled;
        let order2_id = order2.id;
        manager.add_order(order2).await;

        let mut order3 = create_test_order("test-filled", "SOLUSD", 200, 100);
        order3.status = OrderStatus::Filled;
        manager.add_order(order3).await;

        let mut order4 = create_test_order("test-cancelled", "ADAUSD", 1000, 1);
        order4.status = OrderStatus::Cancelled;
        manager.add_order(order4).await;

        let open_orders = manager.get_open_orders().await;
        assert_eq!(open_orders.len(), 2);

        let open_ids: Vec<OrderId> = open_orders.iter().map(|o| o.id).collect();
        assert!(open_ids.contains(&order1_id));
        assert!(open_ids.contains(&order2_id));
    }

    #[tokio::test]
    async fn test_cancel_order() {
        let manager = OrderManager::new();

        let mut order = create_test_order("test-cancel", "BTCUSD", 100, 50000);
        order.status = OrderStatus::Submitted;
        manager.add_order(order.clone()).await;

        let result = manager.cancel_order(&order.id).await;
        assert!(result.is_ok());

        let updated = manager
            .get_order(&order.id)
            .await
            .expect("Order should exist");
        assert_eq!(updated.status, OrderStatus::Cancelled);
    }

    #[tokio::test]
    async fn test_cleanup_old_orders() {
        let manager = OrderManager::new();

        // Create old filled order
        let mut old_order = create_test_order("test-old", "BTCUSD", 100, 50000);
        old_order.status = OrderStatus::Filled;
        old_order.created_at = Utc::now() - Duration::hours(25);
        let old_order_id = old_order.id;
        manager.add_order(old_order).await;

        // Create recent filled order
        let mut recent_order = create_test_order("test-recent", "ETHUSD", 50, 3000);
        recent_order.status = OrderStatus::Filled;
        let recent_order_id = recent_order.id;
        manager.add_order(recent_order).await;

        // Create active order (should never be cleaned)
        let mut active_order = create_test_order("test-active", "SOLUSD", 200, 100);
        active_order.status = OrderStatus::Submitted;
        active_order.created_at = Utc::now() - Duration::hours(25);
        let active_order_id = active_order.id;
        manager.add_order(active_order).await;

        // Cleanup orders older than 24 hours
        manager.cleanup_old_orders(24).await;

        // Old filled order should be removed
        assert!(manager.get_order(&old_order_id).await.is_none());

        // Recent filled order should remain
        assert!(manager.get_order(&recent_order_id).await.is_some());

        // Active order should remain regardless of age
        assert!(manager.get_order(&active_order_id).await.is_some());
    }

    #[tokio::test]
    async fn test_order_statistics() {
        let manager = OrderManager::new();

        // Add orders with different statuses
        let mut order1 = create_test_order("test-stat-1", "BTCUSD", 100, 50000);
        order1.status = OrderStatus::Submitted;
        manager.add_order(order1).await;

        let mut order2 = create_test_order("test-stat-2", "ETHUSD", 50, 3000);
        order2.status = OrderStatus::PartiallyFilled;
        manager.add_order(order2).await;

        let mut order3 = create_test_order("test-stat-3", "SOLUSD", 200, 100);
        order3.status = OrderStatus::Filled;
        manager.add_order(order3).await;

        let mut order4 = create_test_order("test-stat-4", "ADAUSD", 1000, 1);
        order4.status = OrderStatus::Cancelled;
        manager.add_order(order4).await;

        let mut order5 = create_test_order("test-stat-5", "DOTUSD", 300, 10);
        order5.status = OrderStatus::Rejected;
        manager.add_order(order5).await;

        let stats = manager.get_order_stats().await;

        assert_eq!(stats.total_orders, 5);
        assert_eq!(stats.submitted_orders, 1);
        assert_eq!(stats.partially_filled_orders, 1);
        assert_eq!(stats.filled_orders, 1);
        assert_eq!(stats.cancelled_orders, 1);
        assert_eq!(stats.rejected_orders, 1);

        // Fill rate = (filled + partially_filled) / total = 2/5 = 0.4
        assert!((stats.fill_rate - 0.4).abs() < 0.01);
    }

    #[tokio::test]
    async fn test_get_orders_status_filter_only_returns_matching() {
        let manager = OrderManager::new();

        // Add orders with distinct statuses
        let mut submitted = create_test_order("filter-submitted", "BTCUSD", 100, 50000);
        submitted.status = OrderStatus::Submitted;
        manager.add_order(submitted).await;

        let mut filled = create_test_order("filter-filled", "ETHUSD", 50, 3000);
        filled.status = OrderStatus::Filled;
        manager.add_order(filled).await;

        let mut cancelled = create_test_order("filter-cancelled", "SOLUSD", 200, 100);
        cancelled.status = OrderStatus::Cancelled;
        manager.add_order(cancelled).await;

        let mut partial = create_test_order("filter-partial", "ADAUSD", 1000, 1);
        partial.status = OrderStatus::PartiallyFilled;
        manager.add_order(partial).await;

        // Filter for Filled only - must return exactly 1 order
        let filled_orders = manager.get_orders(Some(OrderStatus::Filled)).await;
        assert_eq!(
            filled_orders.len(),
            1,
            "Expected 1 Filled order, got {}. Filter is broken if this returns all orders.",
            filled_orders.len()
        );
        assert_eq!(filled_orders[0].status, OrderStatus::Filled);

        // Filter for Submitted only - must return exactly 1 order
        let submitted_orders = manager.get_orders(Some(OrderStatus::Submitted)).await;
        assert_eq!(submitted_orders.len(), 1);
        assert_eq!(submitted_orders[0].status, OrderStatus::Submitted);

        // Filter for Cancelled only - must return exactly 1 order
        let cancelled_orders = manager.get_orders(Some(OrderStatus::Cancelled)).await;
        assert_eq!(cancelled_orders.len(), 1);
        assert_eq!(cancelled_orders[0].status, OrderStatus::Cancelled);

        // No filter - must return all 4 orders
        let all_orders = manager.get_orders(None).await;
        assert_eq!(all_orders.len(), 4);
    }

    #[tokio::test]
    async fn test_validate_and_add_order_success() {
        let manager = OrderManager::new();
        let order = create_test_order("atomic-001", "BTCUSD", 100, 50000);

        let result = manager.validate_and_add_order(order.clone()).await;
        assert!(result.is_ok(), "First validate_and_add_order should succeed");

        // Verify the order was actually stored
        let retrieved = manager.get_order(&order.id).await;
        assert!(retrieved.is_some(), "Order should exist after atomic add");
    }

    #[tokio::test]
    async fn test_duplicate_order_id_rejected_atomic() {
        let manager = OrderManager::new();
        let order = create_test_order("dup-atomic", "BTCUSD", 100, 50000);

        // First add should succeed
        let result = manager.validate_and_add_order(order.clone()).await;
        assert!(result.is_ok(), "First validate_and_add_order should succeed");

        // Second with same ID should fail
        let result = manager.validate_and_add_order(order).await;
        assert!(result.is_err(), "Duplicate order ID must be rejected");
        let err_msg = result.unwrap_err();
        assert!(
            err_msg.contains("Duplicate"),
            "Error should mention duplicate, got: {}",
            err_msg
        );
    }

    #[tokio::test]
    async fn test_validate_and_add_rejects_invalid_quantity() {
        let manager = OrderManager::new();
        let mut order = create_test_order("atomic-bad-qty", "BTCUSD", 100, 50000);
        order.quantity = Decimal::ZERO;

        let result = manager.validate_and_add_order(order).await;
        assert!(result.is_err(), "Zero quantity should be rejected");

        // Verify no order was stored
        let stored = manager.get_order(&"atomic-bad-qty".to_string().into()).await;
        assert!(stored.is_none(), "Invalid order should not be stored");
    }

    #[tokio::test]
    async fn test_validate_and_add_rejects_empty_symbol() {
        let manager = OrderManager::new();
        let mut order = create_test_order("atomic-bad-sym", "BTCUSD", 100, 50000);
        order.symbol = String::new();

        let result = manager.validate_and_add_order(order).await;
        assert!(result.is_err(), "Empty symbol should be rejected");
    }

    #[tokio::test]
    async fn test_validate_and_add_rejects_invalid_limit_price() {
        let manager = OrderManager::new();
        let mut order = create_test_order("atomic-bad-price", "BTCUSD", 100, 50000);
        order.order_type = OrderType::Limit;
        order.price = Decimal::from(-100);

        let result = manager.validate_and_add_order(order).await;
        assert!(result.is_err(), "Negative limit price should be rejected");
    }

    #[tokio::test]
    async fn test_execution_not_found() {
        let manager = OrderManager::new();

        let execution = ExecutionResult {
            order_id: "nonexistent".to_string().into(),
            symbol: "BTCUSD".to_string(),
            side: common::OrderSide::Buy,
            executed_quantity: Decimal::from(100),
            execution_price: Decimal::from(50000),
            execution_time: Utc::now(),
            commission: Decimal::from(10),
            liquidity_flag: crate::trading_operations::LiquidityFlag::Maker,
        };

        let result = manager.process_execution(&execution).await;
        assert!(result.is_err());
        assert!(result.unwrap_err().contains("not found"));
    }

    fn create_test_execution(order_id: OrderId, quantity: i64, price: i64) -> ExecutionResult {
        ExecutionResult {
            order_id,
            symbol: "BTCUSD".to_string(),
            side: common::OrderSide::Buy,
            executed_quantity: Decimal::from(quantity),
            execution_price: Decimal::from(price),
            execution_time: Utc::now(),
            commission: Decimal::from(1),
            liquidity_flag: crate::trading_operations::LiquidityFlag::Maker,
        }
    }

    #[tokio::test]
    async fn test_overfill_rejected() {
        let manager = OrderManager::new();
        let mut order = create_test_order("overfill-1", "BTCUSD", 100, 50000);
        order.status = OrderStatus::Submitted;
        let oid = order.id;
        manager.add_order(order).await;

        // Fill 80 of 100
        let exec1 = create_test_execution(oid, 80, 150);
        let result = manager.process_execution(&exec1).await;
        assert!(result.is_ok(), "First fill of 80 should succeed");

        // Try to fill 30 more (total would be 110 > 100)
        let exec2 = create_test_execution(oid, 30, 151);
        let result = manager.process_execution(&exec2).await;
        assert!(result.is_err(), "Overfill must be rejected");
        let err = result.unwrap_err();
        assert!(
            err.contains("Overfill"),
            "Error should mention overfill, got: {}",
            err
        );
    }

    #[tokio::test]
    async fn test_fill_on_already_filled_order_rejected() {
        let manager = OrderManager::new();
        let mut order = create_test_order("filled-dup-1", "BTCUSD", 100, 50000);
        order.status = OrderStatus::Filled;
        order.fill_quantity = Decimal::from(100);
        let oid = order.id;
        manager.add_order(order).await;

        // Try to fill an already-filled order
        let exec = create_test_execution(oid, 10, 150);
        let result = manager.process_execution(&exec).await;
        assert!(result.is_err(), "Fill on already-filled order must be rejected");
        let err = result.unwrap_err();
        assert!(
            err.contains("already fully filled"),
            "Error should mention already filled, got: {}",
            err
        );
    }

    #[tokio::test]
    async fn test_exact_fill_succeeds() {
        let manager = OrderManager::new();
        let mut order = create_test_order("exact-fill-1", "BTCUSD", 100, 50000);
        order.status = OrderStatus::Submitted;
        let oid = order.id;
        manager.add_order(order).await;

        // Fill 60
        let exec1 = create_test_execution(oid, 60, 150);
        let result = manager.process_execution(&exec1).await;
        assert!(result.is_ok(), "Partial fill of 60 should succeed");

        // Fill remaining 40 (total = 100 = order qty, should succeed)
        let exec2 = create_test_execution(oid, 40, 151);
        let result = manager.process_execution(&exec2).await;
        assert!(result.is_ok(), "Exact remaining fill of 40 should succeed");

        let updated = manager.get_order(&oid).await;
        assert!(updated.is_some());
        if let Some(o) = updated {
            assert_eq!(o.status, OrderStatus::Filled);
            assert_eq!(o.fill_quantity, Decimal::from(100));
        }
    }
}
