use crate::{MarketUpdate, Order, Fill, TradingMode, MarketDataSource, ExecutionHandler, TimeProvider, Side};
use crate::positions::PositionTracker;
use crate::risk::RiskEngine;
use crate::orderbook::OrderBookManager;
use chrono::{DateTime, Utc};
use std::collections::{BTreeMap, VecDeque};
use std::sync::Arc;
use parking_lot::RwLock;
use serde::{Serialize, Deserialize};

pub mod engine;
pub mod event;
pub mod strategy;
pub mod simple_results;
pub mod trade_tracker;

#[cfg(test)]
mod price_tracking_test;

pub use engine::BacktestEngine;
pub use event::{BacktestEvent, EventType};
pub use strategy::{Strategy, Signal, SignalType};
pub use simple_results::{BacktestResult, BacktestMetrics};
pub use trade_tracker::{TradeTracker, CompletedTrade as TrackedTrade};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompletedTrade {
    pub symbol: String,
    pub side: Side,
    pub timestamp: DateTime<Utc>,
    pub price: f64,
    pub quantity: f64,
    pub commission: f64,
    pub position_after: f64, // Position size after this trade
    pub pnl: Option<f64>, // P&L if position was reduced/closed
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BacktestConfig {
    #[serde(default = "default_name")]
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub strategy: Option<String>,
    pub symbols: Vec<String>,
    #[serde(rename = "startDate")]
    pub start_time: DateTime<Utc>,
    #[serde(rename = "endDate")]
    pub end_time: DateTime<Utc>,
    pub initial_capital: f64,
    pub commission: f64,
    pub slippage: f64,
    #[serde(default = "default_data_frequency")]
    pub data_frequency: String,
}

fn default_name() -> String {
    "Backtest".to_string()
}

fn default_data_frequency() -> String {
    "1d".to_string()
}

#[derive(Debug, Clone)]
pub struct BacktestState {
    pub current_time: DateTime<Utc>,
    pub portfolio_value: f64,
    pub cash: f64,
    pub equity_curve: Vec<(DateTime<Utc>, f64)>,
    pub pending_orders: BTreeMap<String, Order>,
    pub completed_trades: Vec<CompletedTrade>,
}

impl BacktestState {
    pub fn new(initial_capital: f64, start_time: DateTime<Utc>) -> Self {
        Self {
            current_time: start_time,
            portfolio_value: initial_capital,
            cash: initial_capital,
            equity_curve: vec![(start_time, initial_capital)],
            pending_orders: BTreeMap::new(),
            completed_trades: Vec::new(),
        }
    }
    
    pub fn update_portfolio_value(&mut self, value: f64) {
        self.portfolio_value = value;
        
        // Only add a new equity curve point if the timestamp has changed
        // or if it's the first point
        if self.equity_curve.is_empty() || 
           self.equity_curve.last().map(|(t, _)| *t != self.current_time).unwrap_or(true) {
            self.equity_curve.push((self.current_time, value));
        } else {
            // Update the last point with the new value
            if let Some(last) = self.equity_curve.last_mut() {
                last.1 = value;
            }
        }
    }
    
    pub fn add_pending_order(&mut self, order: Order) {
        self.pending_orders.insert(order.id.clone(), order);
    }
    
    pub fn remove_pending_order(&mut self, order_id: &str) -> Option<Order> {
        self.pending_orders.remove(order_id)
    }
    
    pub fn record_fill(&mut self, symbol: String, side: Side, fill: Fill, position_after: f64, position_before: f64, pnl: Option<f64>) {
        self.completed_trades.push(CompletedTrade {
            symbol,
            side,
            timestamp: fill.timestamp,
            price: fill.price,
            quantity: fill.quantity,
            commission: fill.commission,
            position_after,
            pnl,
        });
    }
}

// Event queue for deterministic replay
#[derive(Debug)]
pub struct EventQueue {
    events: VecDeque<BacktestEvent>,
}

impl EventQueue {
    pub fn new() -> Self {
        Self {
            events: VecDeque::new(),
        }
    }
    
    pub fn push(&mut self, event: BacktestEvent) {
        // Insert in time order
        let pos = self.events.iter().position(|e| e.timestamp > event.timestamp)
            .unwrap_or(self.events.len());
        self.events.insert(pos, event);
    }
    
    pub fn pop_until(&mut self, timestamp: DateTime<Utc>) -> Vec<BacktestEvent> {
        let mut events = Vec::new();
        while let Some(event) = self.events.front() {
            if event.timestamp <= timestamp {
                events.push(self.events.pop_front().unwrap());
            } else {
                break;
            }
        }
        events
    }
    
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
    
    pub fn len(&self) -> usize {
        self.events.len()
    }
    
    pub fn peek_next(&self) -> Option<&BacktestEvent> {
        self.events.front()
    }
}