//! Market data types for common use

use crate::types::{OrderSide, Price, Quantity, Symbol};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

/// Market data event types
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(clippy::module_name_repetitions)]
pub enum MarketDataEvent {
    /// Trade execution event
    Trade(TradeEvent),
    /// Quote update (bid/ask) event
    Quote(QuoteEvent),
    /// Bar/candlestick data event
    Bar(BarEvent),
    /// Order book update event
    OrderBook(OrderBookEvent),
    /// News and market information event
    News(NewsEvent),
}

/// Trade event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradeEvent {
    /// Trading symbol
    pub symbol: Symbol,
    /// Trade execution price
    pub price: Price,
    /// Trade quantity
    pub quantity: Quantity,
    /// Trade side (buy or sell)
    pub side: OrderSide,
    /// Trade execution timestamp
    pub timestamp: DateTime<Utc>,
    /// Unique trade identifier
    pub trade_id: String,
}

/// Quote event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuoteEvent {
    /// Trading symbol
    pub symbol: Symbol,
    /// Best bid price
    pub bid_price: Price,
    /// Best bid quantity
    pub bid_quantity: Quantity,
    /// Best ask price
    pub ask_price: Price,
    /// Best ask quantity
    pub ask_quantity: Quantity,
    /// Quote timestamp
    pub timestamp: DateTime<Utc>,
}

/// Bar event (OHLCV)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BarEvent {
    /// Trading symbol
    pub symbol: Symbol,
    /// Opening price
    pub open: Price,
    /// Highest price
    pub high: Price,
    /// Lowest price
    pub low: Price,
    /// Closing price
    pub close: Price,
    /// Trading volume
    pub volume: Quantity,
    /// Bar timestamp
    pub timestamp: DateTime<Utc>,
    /// Bar time interval
    pub interval: BarInterval,
}

/// Bar interval
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum BarInterval {
    /// 1-second interval
    Second1,
    /// 1-minute interval
    Minute1,
    /// 5-minute interval
    Minute5,
    /// 15-minute interval
    Minute15,
    /// 1-hour interval
    Hour1,
    /// 1-day interval
    Day1,
}

/// Order book event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderBookEvent {
    /// Trading symbol
    pub symbol: Symbol,
    /// Bid levels (price, quantity)
    pub bids: Vec<(Price, Quantity)>,
    /// Ask levels (price, quantity)
    pub asks: Vec<(Price, Quantity)>,
    /// Order book timestamp
    pub timestamp: DateTime<Utc>,
}

/// News event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NewsEvent {
    /// Related trading symbol (if applicable)
    pub symbol: Option<Symbol>,
    /// News headline
    pub headline: String,
    /// News content/body
    pub content: String,
    /// News publication timestamp
    pub timestamp: DateTime<Utc>,
    /// News source identifier
    pub source: String,
}

impl MarketDataEvent {
    /// Get the timestamp for any market data event
    pub const fn timestamp(&self) -> Option<DateTime<Utc>> {
        match self {
            MarketDataEvent::Quote(q) => Some(q.timestamp),
            MarketDataEvent::Trade(t) => Some(t.timestamp),
            MarketDataEvent::Bar(b) => Some(b.timestamp),
            MarketDataEvent::OrderBook(o) => Some(o.timestamp),
            MarketDataEvent::News(n) => Some(n.timestamp),
        }
    }
}
