//! Interactive Brokers TWS Integration Examples
//!
//! This file demonstrates how to use the Interactive Brokers adapter
//! for connecting to TWS/Gateway, submitting orders, and handling market data.

use tokio::time::{sleep, Duration};
use tracing::{info, warn};

use super::{BrokerAdapter, BrokerFactory, IBConfig, InteractiveBrokersAdapter};

// Import the types needed for Order creation
use common::{Order, OrderId, Symbol, OrderSide, OrderType, OrderStatus, TimeInForce, Quantity, Price};
use std::collections::HashMap;

/// Basic connection example
pub async fn basic_connection_example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // Configure connection to TWS paper trading
    // Uses environment variables or defaults
    let config = IBConfig::default();

    // Create adapter and connect
    let mut adapter = InteractiveBrokersAdapter::new(config);
    
    info!("Connecting to TWS...");
    adapter.connect().await?;
    
    if adapter.is_connected() {
        info!("Successfully connected to TWS!");
        
        // Keep connection alive for a bit
        sleep(Duration::from_secs(5)).await;
        
        // Disconnect
        adapter.disconnect().await?;
        info!("Disconnected from TWS");
    } else {
        warn!("Failed to connect to TWS");
    }
    
    Ok(())
}

/// Order submission example
pub async fn order_submission_example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let config = IBConfig::default();
    let mut adapter = InteractiveBrokersAdapter::new(config);
    
    // Connect to TWS
    adapter.connect().await?;
    
    if !adapter.is_connected() {
        return Err("Failed to connect to TWS".into());
    }
    
    // Create a simple market order
    let order = Order {
        id: OrderId::new(),
        symbol: Symbol::from("AAPL"),
        side: OrderSide::Buy,
        quantity: Quantity::new(100.0)?,
        order_type: OrderType::Market,
        price: None,
        stop_price: None,
        time_in_force: TimeInForce::Day,
        created_at: chrono::Utc::now(),
        updated_at: chrono::Utc::now(),
        filled_quantity: Quantity::ZERO,
        status: OrderStatus::New,
        metadata: std::collections::HashMap::new(),
    };
    
    // Submit the order
    info!("Submitting market order for 100 shares of AAPL");
    let tws_order_id = adapter.submit_order(&order).await?;
    info!("Order submitted with TWS ID: {}", tws_order_id);
    
    // Wait a bit for order processing
    sleep(Duration::from_secs(2)).await;
    
    // Example of cancelling the order (if still open)
    info!("Cancelling order");
    adapter.cancel_order(&tws_order_id).await?;
    
    adapter.disconnect().await?;
    Ok(())
}

/// Market data subscription example
pub async fn market_data_example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let config = IBConfig::default();
    let mut adapter = InteractiveBrokersAdapter::new(config);
    
    // Connect to TWS
    adapter.connect().await?;
    
    if !adapter.is_connected() {
        return Err("Failed to connect to TWS".into());
    }
    
    // Subscribe to market data for AAPL
    let symbol = Symbol::from("AAPL");
    info!("Subscribing to market data for {}", symbol.to_string());
    let request_id = adapter.request_market_data(&symbol).await?;
    info!("Market data subscription request ID: {}", request_id);
    
    // Start message processing in background
    let adapter_clone = std::sync::Arc::new(adapter);
    let process_handle = {
        let adapter = adapter_clone.clone();
        tokio::spawn(async move {
            if let Err(e) = adapter.process_messages().await {
                warn!("Message processing error: {}", e);
            }
        })
    };
    
    // Let it run for 30 seconds to receive market data
    info!("Receiving market data for 30 seconds...");
    sleep(Duration::from_secs(30)).await;
    
    // Cancel the subscription
    info!("Cancelling market data subscription");
    adapter_clone.cancel_market_data(request_id).await?;
    
    // Stop message processing
    process_handle.abort();
    
    // Disconnect
    let mut adapter_mut = std::sync::Arc::try_unwrap(adapter_clone)
        .map_err(|_| "Failed to unwrap adapter")?;
    adapter_mut.disconnect().await?;
    
    Ok(())
}

/// Account information example
pub async fn account_information_example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let config = IBConfig::default();
    let mut adapter = InteractiveBrokersAdapter::new(config);
    
    // Connect to TWS
    adapter.connect().await?;
    
    if !adapter.is_connected() {
        return Err("Failed to connect to TWS".into());
    }
    
    // Request account updates
    info!("Requesting account updates");
    adapter.request_account_updates().await?;
    
    // Start message processing to receive account updates
    let adapter_clone = std::sync::Arc::new(adapter);
    let process_handle = {
        let adapter = adapter_clone.clone();
        tokio::spawn(async move {
            if let Err(e) = adapter.process_messages().await {
                warn!("Message processing error: {}", e);
            }
        })
    };
    
    // Let it run for 10 seconds to receive account updates
    info!("Receiving account updates for 10 seconds...");
    sleep(Duration::from_secs(10)).await;
    
    // Stop message processing
    process_handle.abort();
    
    // Disconnect
    let mut adapter_mut = std::sync::Arc::try_unwrap(adapter_clone)
        .map_err(|_| "Failed to unwrap adapter")?;
    adapter_mut.disconnect().await?;
    
    Ok(())
}

/// Comprehensive trading workflow example
pub async fn comprehensive_trading_example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let config = IBConfig::default();
    let mut adapter = InteractiveBrokersAdapter::new(config);
    
    info!("=== Comprehensive Trading Workflow Example ===");
    
    // Step 1: Connect
    info!("1. Connecting to TWS...");
    adapter.connect().await?;
    
    // Step 2: Request account information
    info!("2. Requesting account information...");
    adapter.request_account_updates().await?;
    
    // Step 3: Subscribe to market data
    let symbols = vec![
        Symbol::from("AAPL"),
        Symbol::from("GOOGL"),
        Symbol::from("MSFT"),
    ];
    
    let mut market_data_requests = Vec::new();
    for symbol in &symbols {
        info!("3. Subscribing to market data for {}", symbol.to_string());
        let request_id = adapter.request_market_data(symbol).await?;
        market_data_requests.push((symbol.clone(), request_id));
    }
    
    // Step 4: Start message processing
    let adapter_clone = std::sync::Arc::new(adapter);
    let process_handle = {
        let adapter = adapter_clone.clone();
        tokio::spawn(async move {
            if let Err(e) = adapter.process_messages().await {
                warn!("Message processing error: {}", e);
            }
        })
    };
    
    // Step 5: Wait for market data
    info!("4. Receiving market data...");
    sleep(Duration::from_secs(10)).await;
    
    // Step 6: Submit some orders
    info!("5. Submitting orders...");
    let orders = vec![
        Order {
            id: OrderId::new(),
            symbol: Symbol::from("AAPL"),
            side: OrderSide::Buy,
            quantity: Quantity::new(10.0)?,
            order_type: OrderType::Limit,
            price: Some(Price::new(150.00)?),
            stop_price: None,
            time_in_force: TimeInForce::Day,
            created_at: chrono::Utc::now(),
            updated_at: chrono::Utc::now(),
            filled_quantity: Quantity::ZERO,
            status: OrderStatus::New,
            metadata: std::collections::HashMap::new(),
        },
        Order {
            id: OrderId::new(),
            symbol: Symbol::from("GOOGL"),
            side: OrderSide::Sell,
            quantity: Quantity::new(5.0)?,
            order_type: OrderType::Market,
            price: None,
            stop_price: None,
            time_in_force: TimeInForce::Day,
            created_at: chrono::Utc::now(),
            updated_at: chrono::Utc::now(),
            filled_quantity: Quantity::ZERO,
            status: OrderStatus::New,
            metadata: std::collections::HashMap::new(),
        },
    ];
    
    let mut submitted_orders = Vec::new();
    for order in orders {
        let tws_order_id = adapter_clone.submit_order(&order).await?;
        info!("Submitted order: {} -> TWS ID: {}", order.id.to_string(), tws_order_id);
        submitted_orders.push(tws_order_id);
    }
    
    // Step 7: Wait for order processing
    info!("6. Waiting for order processing...");
    sleep(Duration::from_secs(5)).await;
    
    // Step 8: Cancel orders (example)
    info!("7. Cancelling orders...");
    for tws_order_id in submitted_orders {
        adapter_clone.cancel_order(&tws_order_id).await?;
        info!("Cancelled order: {}", tws_order_id);
    }
    
    // Step 9: Unsubscribe from market data
    info!("8. Unsubscribing from market data...");
    for (_symbol, request_id) in market_data_requests {
        adapter_clone.cancel_market_data(request_id).await?;
    }
    
    // Step 10: Stop processing and disconnect
    info!("9. Stopping message processing and disconnecting...");
    process_handle.abort();
    
    let mut adapter_mut = std::sync::Arc::try_unwrap(adapter_clone)
        .map_err(|_| "Failed to unwrap adapter")?;
    adapter_mut.disconnect().await?;
    
    info!("=== Trading workflow completed successfully ===");
    Ok(())
}

/// Run all examples
pub async fn run_all_examples() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    info!("Running Interactive Brokers integration examples...");
    
    // Note: These examples require TWS or IB Gateway to be running
    // and configured for API connections
    
    println!("Example 1: Basic Connection");
    if let Err(e) = basic_connection_example().await {
        warn!("Basic connection example failed: {}", e);
    }
    
    sleep(Duration::from_secs(2)).await;
    
    println!("\nExample 2: Order Submission");
    if let Err(e) = order_submission_example().await {
        warn!("Order submission example failed: {}", e);
    }
    
    sleep(Duration::from_secs(2)).await;
    
    println!("\nExample 3: Market Data");
    if let Err(e) = market_data_example().await {
        warn!("Market data example failed: {}", e);
    }
    
    sleep(Duration::from_secs(2)).await;
    
    println!("\nExample 4: Account Information");
    if let Err(e) = account_information_example().await {
        warn!("Account information example failed: {}", e);
    }
    
    sleep(Duration::from_secs(2)).await;
    
    println!("\nExample 5: Comprehensive Trading Workflow");
    if let Err(e) = comprehensive_trading_example().await {
        warn!("Comprehensive trading example failed: {}", e);
    }
    
    info!("All examples completed!");
    Ok(())
}

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

    #[tokio::test]
    async fn test_example_creation() {
        // Test that we can create orders and configurations without errors
        let config = IBConfig::default();
        // Port depends on environment, just verify it's valid
        assert!(config.port > 0);
        
        let order = Order {
            id: OrderId::new(),
            symbol: Symbol::from("AAPL"),
            side: Side::Buy,
            quantity: Quantity::new(100.0).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            order_type: OrderType::Market,
            price: None,
            stop_price: None,
            time_in_force: TimeInForce::Day,
            created_at: chrono::Utc::now(),
            updated_at: chrono::Utc::now(),
            filled_quantity: Quantity::ZERO,
            status: OrderStatus::New,
            metadata: std::collections::HashMap::new(),
        };
        
        assert_eq!(order.side, OrderSide::Buy);
        assert_eq!(order.order_type, OrderType::Market);
    }
}