use async_trait::async_trait;
use crate::events::EventBus;
use crate::{ExecutionHandler, TimeProvider, MarketDataSource};
use std::sync::Arc;

pub mod backtest;
pub mod paper;
pub mod live;

pub use backtest::BacktestEngine;
pub use paper::PaperEngine;
pub use live::{LiveEngine, BrokerConnection};

/// Trading mode configuration
#[derive(Debug, Clone)]
pub enum TradingMode {
    Backtest {
        start_time: chrono::DateTime<chrono::Utc>,
        end_time: chrono::DateTime<chrono::Utc>,
        speed_multiplier: f64,
    },
    Paper {
        starting_capital: f64,
    },
    Live {
        broker: String,
        account_id: String,
    },
}

/// Common interface for all trading engines
#[async_trait]
pub trait TradingEngine: Send + Sync {
    /// Start the trading engine
    async fn start(&mut self, event_bus: &mut EventBus) -> Result<(), String>;
    
    /// Stop the trading engine
    async fn stop(&mut self) -> Result<(), String>;
    
    /// Get the execution handler for this mode
    fn get_execution_handler(&self) -> Arc<dyn ExecutionHandler>;
    
    /// Get the time provider for this mode
    fn get_time_provider(&self) -> Arc<dyn TimeProvider>;
}

/// Create a trading engine for the specified mode
pub fn create_engine_for_mode(
    mode: &TradingMode,
) -> Result<Box<dyn TradingEngine>, String> {
    match mode {
        TradingMode::Backtest { start_time, end_time, speed_multiplier } => {
            // For backtest, we need to create a market data source
            // This would typically load historical data
            let market_data = create_backtest_data_source()?;
            
            Ok(Box::new(BacktestEngine::new(
                *start_time,
                *end_time,
                *speed_multiplier,
                market_data,
            )))
        }
        TradingMode::Paper { starting_capital } => {
            // For paper trading, we need a real-time data source
            let market_data = create_realtime_data_source()?;
            
            Ok(Box::new(PaperEngine::new(
                *starting_capital,
                market_data,
            )))
        }
        TradingMode::Live { broker, account_id } => {
            // For live trading, we need a broker connection
            let broker_connection = create_broker_connection(broker)?;
            
            Ok(Box::new(LiveEngine::new(
                broker.clone(),
                account_id.clone(),
                broker_connection,
            )))
        }
    }
}

// Helper functions to create data sources and broker connections
// These would be implemented based on your specific requirements

fn create_backtest_data_source() -> Result<Box<dyn MarketDataSource>, String> {
    // TODO: Implement actual backtest data source
    // For now, return a placeholder
    Err("Backtest data source not implemented yet".to_string())
}

fn create_realtime_data_source() -> Result<Box<dyn MarketDataSource>, String> {
    // TODO: Implement actual real-time data source
    // For now, return a placeholder
    Err("Real-time data source not implemented yet".to_string())
}

fn create_broker_connection(broker: &str) -> Result<Arc<dyn BrokerConnection>, String> {
    match broker {
        "mock" => Ok(Arc::new(live::MockBroker::new())),
        _ => Err(format!("Unknown broker: {}", broker)),
    }
}