"""Event types for the strategy framework and event bus.

All events carry nanosecond-precision timestamps and are immutable (frozen).
"""

from __future__ import annotations

import time
from dataclasses import dataclass, field
from typing import Any, Dict, Optional


def _ts_ns() -> int:
    return int(time.time() * 1_000_000_000)


@dataclass(frozen=True)
class Event:
    """Base event — all events inherit from this."""

    ts_event: int = field(default_factory=_ts_ns)
    ts_init: int = field(default_factory=_ts_ns)


@dataclass(frozen=True)
class BarEvent(Event):
    """A new bar (OHLCV candle) was received."""

    symbol: str = ""
    timeframe: str = "1Min"
    open: float = 0.0
    high: float = 0.0
    low: float = 0.0
    close: float = 0.0
    volume: float = 0.0
    vwap: float = 0.0


@dataclass(frozen=True)
class QuoteEvent(Event):
    """A new bid/ask quote was received."""

    symbol: str = ""
    bid: float = 0.0
    ask: float = 0.0
    bid_size: float = 0.0
    ask_size: float = 0.0

    @property
    def mid(self) -> float:
        return (self.bid + self.ask) / 2.0 if self.bid and self.ask else 0.0

    @property
    def spread(self) -> float:
        return self.ask - self.bid if self.bid and self.ask else 0.0


@dataclass(frozen=True)
class TradeEvent(Event):
    """A trade (tick) was observed."""

    symbol: str = ""
    price: float = 0.0
    size: float = 0.0
    exchange: str = ""


@dataclass(frozen=True)
class OrderEvent(Event):
    """An order state change occurred."""

    order_id: str = ""
    symbol: str = ""
    side: str = ""
    qty: float = 0.0
    order_type: str = ""
    status: str = ""
    strategy_id: str = ""


@dataclass(frozen=True)
class FillEvent(Event):
    """An order was (partially) filled."""

    order_id: str = ""
    symbol: str = ""
    side: str = ""
    fill_qty: float = 0.0
    fill_price: float = 0.0
    commission: float = 0.0
    strategy_id: str = ""

    @property
    def notional(self) -> float:
        return self.fill_qty * self.fill_price


@dataclass(frozen=True)
class PositionEvent(Event):
    """A position was opened, changed, or closed."""

    symbol: str = ""
    qty: float = 0.0
    avg_entry_price: float = 0.0
    market_value: float = 0.0
    unrealized_pnl: float = 0.0
    realized_pnl: float = 0.0
    action: str = ""  # "opened", "changed", "closed"
    strategy_id: str = ""


@dataclass(frozen=True)
class TimeEvent(Event):
    """A timer or time alert fired."""

    name: str = ""


@dataclass(frozen=True)
class SignalEvent(Event):
    """A user-defined signal was emitted."""

    name: str = ""
    value: float = 0.0
    data: Dict[str, Any] = field(default_factory=dict)
    source: str = ""
