"""Feed wrappers for price data sources."""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class BinanceWS:
    """Binance WebSocket price feed.

    Usage: BinanceWS("btcusdt")
    """

    symbol: str
    _type: str = "binance_ws"


@dataclass
class RESTFeed:
    """Generic REST API price feed.

    Usage: RESTFeed("https://api.example.com/price", interval=5.0)
    """

    url: str
    interval: float = 5.0
    _type: str = "rest"


@dataclass
class PolymarketBook:
    """Polymarket orderbook feed.

    Usage: PolymarketBook("will-btc-hit-100k")
    """

    market_slug: str
    _type: str = "polymarket_book"


@dataclass
class KalshiBook:
    """Kalshi orderbook feed.

    Usage: KalshiBook("KXBTC-25FEB16")
    """

    ticker: str
    _type: str = "kalshi_book"


@dataclass
class PredictItFeed:
    """PredictIt market price feed.

    Polls the PredictIt API for contract prices.

    Usage: PredictItFeed(market_id=7456, contract_id=28562)
    """

    market_id: int
    contract_id: int | None = None
    interval: float = 5.0
    _type: str = "predictit"


@dataclass
class ManifoldFeed:
    """Manifold Markets probability feed.

    Polls the Manifold API for market probability.

    Usage: ManifoldFeed("will-btc-hit-100k-by-2026")
    """

    slug: str
    interval: float = 5.0
    _type: str = "manifold"


@dataclass
class ESPNFeed:
    """ESPN live scoreboard feed.

    Polls ESPN for live game scores.

    Usage: ESPNFeed("basketball", "nba")
    """

    sport: str
    league: str
    event_id: str | None = None
    interval: float = 10.0
    _type: str = "espn"


@dataclass
class NWSFeed:
    """National Weather Service feed.

    Two modes:
      - forecast: temperature, wind, precipitation for a grid point
      - alerts: active weather alerts for a state

    Usage:
        NWSFeed(office="TOP", grid_x=31, grid_y=80)  # forecast
        NWSFeed(state="FL", mode="alerts")             # alerts
    """

    office: str = ""
    grid_x: int = 0
    grid_y: int = 0
    state: str = ""
    mode: str = "forecast"
    user_agent: str = "Horizon-SDK/0.5.0"
    interval: float = 60.0
    _type: str = "nws"


@dataclass
class RESTJsonPathFeed:
    """Enhanced REST feed with JSON path extraction.

    Uses dot-notation paths to map any JSON field to price/bid/ask/volume.

    Usage:
        RESTJsonPathFeed(
            url="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd",
            price_path="bitcoin.usd",
        )
    """

    url: str
    price_path: str | None = None
    bid_path: str | None = None
    ask_path: str | None = None
    volume_path: str | None = None
    interval: float = 5.0
    _type: str = "rest_json_path"


@dataclass
class ChainlinkFeed:
    """Chainlink on-chain price oracle feed.

    Reads price data from a Chainlink aggregator proxy contract via
    JSON-RPC eth_call. Works with any EVM chain (Ethereum, Arbitrum,
    Polygon, BSC).

    Usage:
        ChainlinkFeed(
            contract_address="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
            rpc_url="https://eth.llamarpc.com",
        )
    """

    contract_address: str
    rpc_url: str
    decimals: int = 8
    interval: float = 10.0
    _type: str = "chainlink"


@dataclass
class MempoolFeed:
    """Polygon mempool watcher feed.

    Monitors pending transactions to Polymarket CTF exchange contracts
    for large order flow visibility.

    Usage:
        MempoolFeed(rpc_url="https://polygon-rpc.com")
    """

    rpc_url: str = ""
    ctf_addresses: list[str] = field(default_factory=lambda: [
        "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E",
        "0xC5d563A36AE78145C45a50134d48A1215220f80a",
    ])
    interval: float = 2.0
    _type: str = "mempool"


@dataclass
class AlpacaFeed:
    """Alpaca Markets real-time stock data feed.

    Streams trades and quotes via WebSocket for stock symbols.

    Usage:
        AlpacaFeed(symbols=["AAPL", "SPY"])
        AlpacaFeed(symbols=["TLT"], data_source="sip")
    """

    symbols: list[str] = field(default_factory=list)
    api_key: str | None = None
    api_secret: str | None = None
    data_source: str = "iex"
    _type: str = "alpaca"

    def __post_init__(self):
        import os
        if self.api_key is None:
            self.api_key = os.environ.get("ALPACA_API_KEY") or os.environ.get("APCA_API_KEY_ID")
        if self.api_secret is None:
            self.api_secret = os.environ.get("ALPACA_API_SECRET") or os.environ.get("APCA_API_SECRET_KEY")


@dataclass
class CalendarFeed:
    """Calendar/event feed for economic events and earnings.

    Polls bundled or API-provided event data, maps nearest event to
    FeedSnapshot fields (bid=seconds_to_event, ask=event_type_code).

    Usage:
        CalendarFeed()  # uses bundled FOMC/CPI dates
        CalendarFeed(api_url="https://api.example.com/events")
    """

    events_json: str = ""
    api_url: str = ""
    interval: float = 300.0
    _type: str = "calendar"

    def __post_init__(self):
        if not self.events_json:
            try:
                from horizon.calendar_events import bundled_events_json
                self.events_json = bundled_events_json()
            except Exception:
                self.events_json = "[]"


@dataclass
class TreasuryFeed:
    """Treasury yield curve feed via FRED API.

    Polls the Federal Reserve Economic Data API for yield curve data.

    Usage:
        TreasuryFeed(api_key="your_fred_api_key")
        TreasuryFeed()  # uses FRED_API_KEY env var
    """

    api_key: str | None = None
    series_ids: list[str] = field(default_factory=lambda: [
        "DGS1MO", "DGS3MO", "DGS6MO", "DGS1", "DGS2",
        "DGS5", "DGS10", "DGS20", "DGS30",
    ])
    primary_series: str = "DGS10"
    interval: float = 300.0
    _type: str = "treasury"

    def __post_init__(self):
        import os
        if self.api_key is None:
            self.api_key = os.environ.get("FRED_API_KEY", "")


@dataclass
class CoinbaseFeed:
    """Coinbase Advanced Trade real-time price feed.

    Streams ticker data via WebSocket for crypto pairs.

    Usage:
        CoinbaseFeed(product_ids=["BTC-USD", "ETH-USD"])
    """

    product_ids: list[str] = field(default_factory=list)
    api_key: str | None = None
    api_secret: str | None = None
    _type: str = "coinbase"

    def __post_init__(self):
        import os
        if self.api_key is None:
            self.api_key = os.environ.get("COINBASE_API_KEY")
        if self.api_secret is None:
            self.api_secret = os.environ.get("COINBASE_API_SECRET")


@dataclass
class RobinhoodFeed:
    """Robinhood Crypto price feed (REST polling).

    Polls Robinhood for crypto quotes at a configurable interval.

    Usage:
        RobinhoodFeed(symbols=["BTC-USD", "ETH-USD"])
    """

    symbols: list[str] = field(default_factory=list)
    api_key: str | None = None
    interval: float = 5.0
    _type: str = "robinhood"

    def __post_init__(self):
        import os
        if self.api_key is None:
            self.api_key = os.environ.get("ROBINHOOD_API_KEY")


@dataclass
class IBKRFeed:
    """Interactive Brokers market data feed (REST polling).

    Polls IBKR Client Portal API for price snapshots.
    Supports stocks, options, futures, and ForecastEx event contracts.

    Usage:
        IBKRFeed(conids=["265598"])         # AAPL
        IBKRFeed(conids=["265598", "8314"])  # AAPL + SPY
    """

    conids: list[str] = field(default_factory=list)
    access_token: str | None = None
    api_url: str | None = None
    paper: bool = True
    interval: float = 5.0
    _type: str = "ibkr"

    def __post_init__(self):
        import os
        if self.access_token is None:
            self.access_token = os.environ.get("IBKR_ACCESS_TOKEN")
        if self.api_url is None:
            if self.paper:
                self.api_url = "https://paper-api.ibkr.com/v1/api"
            else:
                self.api_url = "https://api.ibkr.com/v1/api"
