from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timezone
from decimal import Decimal
from typing import Iterable

CORE_COINS = ("BTC", "ETH", "SOL", "LINK")
RESEARCH_ALT_COINS = ("WLD", "SUI", "ENA", "BCH")
OPTIONAL_COINS = ("HYPE",)
DEFAULT_CONTEXT_UNIVERSE = CORE_COINS + RESEARCH_ALT_COINS + OPTIONAL_COINS


@dataclass(frozen=True)
class CoinMarketContext:
    coin: str
    rsi: Decimal
    sma_fast: Decimal
    sma_slow: Decimal
    atr: Decimal
    funding: Decimal
    volume: Decimal
    mid: Decimal
    spread_pct: Decimal | None
    timestamp: datetime
    reliability_score: Decimal
    stale_data: bool
    l2_available: bool
    open_interest: Decimal = Decimal("0")
    premium: Decimal = Decimal("0")
    oracle_px: Decimal = Decimal("0")
    mark_px: Decimal = Decimal("0")
    prev_day_px: Decimal = Decimal("0")
    day_ntl_vlm: Decimal = Decimal("0")
    bid_depth_notional_5: Decimal = Decimal("0")
    ask_depth_notional_5: Decimal = Decimal("0")
    buy_impact_1k_pct: Decimal | None = None
    sell_impact_1k_pct: Decimal | None = None
    buy_impact_5k_pct: Decimal | None = None
    sell_impact_5k_pct: Decimal | None = None

    def age_seconds(self, now: datetime | None = None) -> float:
        now = now or datetime.now(timezone.utc)
        ts = self.timestamp if self.timestamp.tzinfo else self.timestamp.replace(tzinfo=timezone.utc)
        return max(0.0, (now - ts).total_seconds())


@dataclass(frozen=True)
class MarketContextSnapshot:
    contexts: dict[str, CoinMarketContext]

    @property
    def coins(self) -> set[str]:
        return set(self.contexts)

    @classmethod
    def from_coin_contexts(cls, contexts: Iterable[CoinMarketContext]) -> "MarketContextSnapshot":
        return cls({ctx.coin.upper(): ctx for ctx in contexts})

    def get(self, coin: str) -> CoinMarketContext:
        return self.contexts[coin.upper()]
