#![deny(clippy::all)]

// Existing modules
pub mod core;
pub mod adapters;
pub mod orderbook;
pub mod risk;
pub mod positions;
#[cfg(not(test))]
pub mod api;
pub mod analytics;
pub mod indicators;
pub mod backtest;
pub mod strategies;

// Re-export commonly used types
pub use positions::{Position, PositionUpdate, TradeRecord, ClosedTrade};
pub use risk::{RiskLimits, RiskCheckResult, RiskMetrics};

// Type alias for backtest compatibility
pub type MarketData = MarketUpdate;

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use parking_lot::RwLock;

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

// Core traits that allow different implementations based on mode
#[async_trait::async_trait]
pub trait MarketDataSource: Send + Sync {
    async fn get_next_update(&mut self) -> Option<MarketUpdate>;
    fn seek_to_time(&mut self, timestamp: DateTime<Utc>) -> Result<(), String>;
    fn as_any(&self) -> &dyn std::any::Any;
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}

#[async_trait::async_trait]
pub trait ExecutionHandler: Send + Sync {
    async fn execute_order(&mut self, order: Order) -> Result<ExecutionResult, String>;
    fn get_fill_simulator(&self) -> Option<&dyn FillSimulator>;
}

pub trait TimeProvider: Send + Sync {
    fn now(&self) -> DateTime<Utc>;
    fn sleep_until(&self, target: DateTime<Utc>) -> Result<(), String>;
    fn as_any(&self) -> &dyn std::any::Any;
}

pub trait FillSimulator: Send + Sync {
    fn simulate_fill(&self, order: &Order, orderbook: &OrderBookSnapshot) -> Option<Fill>;
}

// Main trading core that works across all modes
pub struct TradingCore {
    mode: TradingMode,
    pub market_data_source: Arc<RwLock<Box<dyn MarketDataSource>>>,
    pub execution_handler: Arc<RwLock<Box<dyn ExecutionHandler>>>,
    pub time_provider: Arc<Box<dyn TimeProvider>>,
    pub orderbooks: Arc<orderbook::OrderBookManager>,
    pub risk_engine: Arc<risk::RiskEngine>,
    pub position_tracker: Arc<positions::PositionTracker>,
}

// Core types used across the system
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketUpdate {
    pub symbol: String,
    pub timestamp: DateTime<Utc>,
    pub data: MarketDataType,
}

// Market microstructure parameters
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketMicrostructure {
    pub symbol: String,
    pub avg_spread_bps: f64,
    pub daily_volume: f64,
    pub avg_trade_size: f64,
    pub volatility: f64,
    pub tick_size: f64,
    pub lot_size: f64,
    pub intraday_volume_profile: Vec<f64>, // 24 hourly buckets
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MarketDataType {
    Quote(Quote),
    Trade(Trade),
    Bar(Bar),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Quote {
    pub bid: f64,
    pub ask: f64,
    pub bid_size: f64,
    pub ask_size: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trade {
    pub price: f64,
    pub size: f64,
    pub side: Side,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bar {
    pub open: f64,
    pub high: f64,
    pub low: f64,
    pub close: f64,
    pub volume: f64,
    pub vwap: Option<f64>,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum Side {
    Buy,
    Sell,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Order {
    pub id: String,
    pub symbol: String,
    pub side: Side,
    pub quantity: f64,
    pub order_type: OrderType,
    pub time_in_force: TimeInForce,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OrderType {
    Market,
    Limit { price: f64 },
    Stop { stop_price: f64 },
    StopLimit { stop_price: f64, limit_price: f64 },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TimeInForce {
    Day,
    GTC,
    IOC,
    FOK,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionResult {
    pub order_id: String,
    pub status: OrderStatus,
    pub fills: Vec<Fill>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OrderStatus {
    Pending,
    Accepted,
    PartiallyFilled,
    Filled,
    Cancelled,
    Rejected(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Fill {
    pub timestamp: DateTime<Utc>,
    pub price: f64,
    pub quantity: f64,
    pub commission: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderBookSnapshot {
    pub symbol: String,
    pub timestamp: DateTime<Utc>,
    pub bids: Vec<PriceLevel>,
    pub asks: Vec<PriceLevel>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceLevel {
    pub price: f64,
    pub size: f64,
    pub order_count: Option<u32>,
}

impl TradingCore {
    pub fn new(
        mode: TradingMode,
        market_data_source: Box<dyn MarketDataSource>,
        execution_handler: Box<dyn ExecutionHandler>,
        time_provider: Box<dyn TimeProvider>,
    ) -> Self {
        Self {
            mode,
            market_data_source: Arc::new(RwLock::new(market_data_source)),
            execution_handler: Arc::new(RwLock::new(execution_handler)),
            time_provider: Arc::new(time_provider),
            orderbooks: Arc::new(orderbook::OrderBookManager::new()),
            risk_engine: Arc::new(risk::RiskEngine::new()),
            position_tracker: Arc::new(positions::PositionTracker::new()),
        }
    }
    
    pub fn get_mode(&self) -> &TradingMode {
        &self.mode
    }
    
    pub fn get_time(&self) -> DateTime<Utc> {
        self.time_provider.now()
    }
}