use async_trait::async_trait;
use crate::{MarketUpdate, Fill, OrderType};
use crate::backtest::Strategy as OldStrategy;
use crate::risk::RiskLimits;
use std::sync::Arc;
use parking_lot::RwLock;

// Placeholder types for new strategy framework (will be replaced when framework module is activated)
#[async_trait]
pub trait NewStrategy: Send + Sync {
    async fn init(&mut self, context: &StrategyContext) -> Result<(), String>;
    async fn on_data(&mut self, data: &MarketUpdate, context: &StrategyContext) -> Vec<Signal>;
    async fn on_fill(&mut self, order_id: &str, fill: &Fill, context: &StrategyContext);
    async fn shutdown(&mut self, context: &StrategyContext) -> Result<(), String>;
    fn get_state(&self) -> serde_json::Value;
}

pub struct StrategyContext {
    pub account_id: String,
    pub starting_capital: f64,
}

impl StrategyContext {
    pub fn new() -> Self {
        Self {
            account_id: "default".to_string(),
            starting_capital: 100_000.0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum Signal {
    Buy {
        symbol: String,
        quantity: f64,
        order_type: OrderType,
    },
    Sell {
        symbol: String,
        quantity: f64,
        order_type: OrderType,
    },
    CancelOrder {
        order_id: String,
    },
    UpdateRiskLimits {
        limits: RiskLimits,
    },
}



/// Adapter to use new strategies with old interface
pub struct NewToOldStrategyAdapter {
    inner: Arc<RwLock<Box<dyn NewStrategy>>>,
    context: Arc<StrategyContext>,
}

impl NewToOldStrategyAdapter {
    pub fn new(strategy: Box<dyn NewStrategy>, context: Arc<StrategyContext>) -> Self {
        Self {
            inner: Arc::new(RwLock::new(strategy)),
            context,
        }
    }
}

impl OldStrategy for NewToOldStrategyAdapter {
    fn on_market_data(&mut self, data: &crate::MarketData) -> Vec<crate::backtest::strategy::Signal> {
        // Convert MarketData to MarketUpdate if needed
        let market_update = data.clone(); // Assuming MarketData is type alias for MarketUpdate
        
        // Need to block on async call since old trait is sync
        let signals = tokio::task::block_in_place(|| {
            tokio::runtime::Handle::current().block_on(async {
                let mut strategy = self.inner.write();
                strategy.on_data(&market_update, &self.context).await
            })
        });
        
        // Convert new signals to old format
        signals.into_iter().map(|signal| {
            match signal {
                Signal::Buy { symbol, quantity, .. } => {
                    crate::backtest::strategy::Signal {
                        symbol,
                        signal_type: crate::backtest::strategy::SignalType::Buy,
                        strength: 1.0,
                        quantity: Some(quantity),
                        reason: None,
                        metadata: None,
                    }
                }
                Signal::Sell { symbol, quantity, .. } => {
                    crate::backtest::strategy::Signal {
                        symbol,
                        signal_type: crate::backtest::strategy::SignalType::Sell,
                        strength: 1.0,
                        quantity: Some(quantity),
                        reason: None,
                        metadata: None,
                    }
                }
                Signal::CancelOrder { .. } => {
                    // Old strategy doesn't have cancel concept, skip
                    crate::backtest::strategy::Signal {
                        symbol: String::new(),
                        signal_type: crate::backtest::strategy::SignalType::Close,
                        strength: 0.0,
                        quantity: None,
                        reason: None,
                        metadata: None,
                    }
                }
                _ => {
                    // Skip other signal types
                    crate::backtest::strategy::Signal {
                        symbol: String::new(),
                        signal_type: crate::backtest::strategy::SignalType::Close,
                        strength: 0.0,
                        quantity: None,
                        reason: None,
                        metadata: None,
                    }
                }
            }
        }).filter(|s| !s.symbol.is_empty()).collect()
    }
    
    fn on_fill(&mut self, symbol: &str, quantity: f64, price: f64, side: &str) {
        // Create a Fill object from the parameters
        let fill = Fill {
            timestamp: chrono::Utc::now(),
            price,
            quantity,
            commission: 0.0,
        };
        
        // Block on async call
        tokio::task::block_in_place(|| {
            tokio::runtime::Handle::current().block_on(async {
                let mut strategy = self.inner.write();
                strategy.on_fill(&format!("order_{}", symbol), &fill, &self.context).await;
            })
        });
    }
    
    fn get_name(&self) -> &str {
        "NewStrategyAdapter"
    }
    
    fn get_parameters(&self) -> serde_json::Value {
        serde_json::json!({
            "adapter": "NewToOldStrategyAdapter",
            "context": {
                "account_id": self.context.account_id,
                "starting_capital": self.context.starting_capital,
            }
        })
    }
}

/// Adapter to use old strategies with new interface
pub struct OldToNewStrategyAdapter {
    inner: Box<dyn OldStrategy>,
}

impl OldToNewStrategyAdapter {
    pub fn new(strategy: Box<dyn OldStrategy>) -> Self {
        Self { inner: strategy }
    }
}

#[async_trait]
impl NewStrategy for OldToNewStrategyAdapter {
    async fn init(&mut self, _context: &StrategyContext) -> Result<(), String> {
        // Old strategy doesn't have init
        Ok(())
    }
    
    async fn on_data(&mut self, data: &MarketUpdate, _context: &StrategyContext) -> Vec<Signal> {
        // Call sync method from async context
        let signals = self.inner.on_market_data(data);
        
        // Convert old signals to new format
        signals.into_iter().filter_map(|signal| {
            match signal.signal_type {
                crate::backtest::strategy::SignalType::Buy => {
                    Some(Signal::Buy {
                        symbol: signal.symbol,
                        quantity: signal.quantity.unwrap_or(100.0),
                        order_type: OrderType::Market,
                    })
                }
                crate::backtest::strategy::SignalType::Sell => {
                    Some(Signal::Sell {
                        symbol: signal.symbol,
                        quantity: signal.quantity.unwrap_or(100.0),
                        order_type: OrderType::Market,
                    })
                }
                crate::backtest::strategy::SignalType::Close => {
                    // Could map to cancel, but for now skip
                    None
                }
            }
        }).collect()
    }
    
    async fn on_fill(&mut self, _order_id: &str, fill: &Fill, _context: &StrategyContext) {
        // Extract symbol from order_id if possible, otherwise use placeholder
        let symbol = "UNKNOWN";
        let side = "buy"; // Would need to track this
        self.inner.on_fill(symbol, fill.quantity, fill.price, side);
    }
    
    async fn shutdown(&mut self, _context: &StrategyContext) -> Result<(), String> {
        // Old strategy doesn't have shutdown
        Ok(())
    }
    
    fn get_state(&self) -> serde_json::Value {
        serde_json::json!({
            "adapter": "OldToNewStrategyAdapter",
            "inner_strategy": self.inner.get_name(),
            "parameters": self.inner.get_parameters()
        })
    }
}

