"""Event system for the backtesting framework.

This module defines the event hierarchy that flows through the backtesting engine.
Events represent different stages of the trading process and enable loose coupling
between components through an event-driven architecture.

Event Flow:
    StockEvent → Strategy → SignalEvent → Portfolio → OrderEvent → ExecutionHandler → FillEvent → Portfolio

This ensures proper chronological processing and prevents look-ahead bias.
"""

from dataclasses import dataclass
import datetime
from .models import StockCandle


class Event:
    """Base class for all events in the backtesting system.
    
    All events inherit from this class to ensure type consistency
    and enable polymorphic event handling in the engine.
    """
    pass


class SecurityEvent(Event):
    """Base class for events related to financial securities.
    
    Provides a category for market data events that contain
    information about specific financial instruments.
    """
    pass


@dataclass
class StockEvent(SecurityEvent):
    """Market data event containing OHLCV candle information.
    
    This event carries new market data (price and volume) for a specific
    stock at a specific timestamp. It's the primary input to strategies
    and triggers the trading decision process.
    
    Attributes:
        payload: StockCandle containing symbol, timestamp, OHLCV data
    
    Flow:
        DataHandler → StockEvent → Strategy.on_stock_event()
                                 → Portfolio.on_stock_event() (for equity tracking)
    """
    payload: StockCandle


@dataclass
class SignalEvent(Event):
    """Trading signal generated by a strategy.
    
    Represents a strategy's intent to buy or sell a security.
    The signal doesn't specify quantity - that's determined by the Portfolio
    using a Sizer component.
    
    Attributes:
        symbol: Stock symbol to trade (e.g., 'AAPL')
        signal: Trading action ('buy', 'sell', 'sell_all')
        timestamp: When the signal was generated
    
    Flow:
        Strategy.signal() → SignalEvent → Portfolio.on_signal_event()
    """
    symbol: str
    signal: str  # buy, sell, sell_all
    timestamp: datetime.datetime


@dataclass
class OrderEvent(Event):
    """Order to be executed by the execution handler.
    
    Created by the Portfolio after receiving a SignalEvent and determining
    the appropriate quantity using a Sizer. Contains all information needed
    for order execution.
    
    Attributes:
        symbol: Stock symbol to trade
        signal: Trading direction ('buy' or 'sell')
        timestamp: When the order was created
        quantity: Number of shares to trade (positive for both buy/sell)
    
    Flow:
        Portfolio.on_signal_event() → OrderEvent → ExecutionHandler.on_order_event()
    """
    symbol: str
    signal: str  # buy, sell
    timestamp: datetime.datetime
    quantity: int


@dataclass
class FillEvent(Event):
    """Confirmation of an executed order with actual fill details.
    
    Generated by the ExecutionHandler after simulating order execution.
    Contains the actual execution price (including slippage) and commission
    costs. This is what updates the Portfolio's positions and cash.
    
    Attributes:
        symbol: Stock symbol that was traded
        timestamp: When the order was filled
        quantity: Number of shares filled (positive for both buy/sell)
        fill_price: Actual execution price (after slippage)
        commission: Transaction cost charged
        signal: Direction of the trade ('buy' or 'sell')
    
    Flow:
        ExecutionHandler.on_order_event() → FillEvent → Portfolio.on_fill_event()
    """
    symbol: str
    timestamp: datetime.datetime
    quantity: int
    fill_price: float
    commission: float
    signal: str  # buy, sell


