"""
Market data provider interface and registry.

To add a new provider:
1. Create providers/your_provider.py
2. Subclass MarketDataProvider
3. Register in PROVIDER_REGISTRY below
"""
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import AsyncIterator

from app.domain.events import Event


class MarketDataProvider(ABC):
    """
    Base class for all market-data feed adapters.

    Lifecycle:  connect() → subscribe() → stream() → close()
    """

    name: str = "unknown"

    @abstractmethod
    async def connect(self) -> None:
        """Establish connection to the data source."""

    @abstractmethod
    async def subscribe(self, symbols: list[str]) -> None:
        """Subscribe to symbols. May be called after reconnect."""

    @abstractmethod
    async def stream(self) -> AsyncIterator[Event]:
        """Yield normalized domain events. Must handle reconnect internally."""
        yield  # type: ignore

    @abstractmethod
    async def close(self) -> None:
        """Graceful shutdown."""


def get_provider(name: str) -> MarketDataProvider:
    """Factory: instantiate provider by name."""
    from app.providers.binance import BinanceProvider
    from app.providers.alpaca import AlpacaProvider
    from app.providers.bybit import BybitProvider

    registry: dict[str, type[MarketDataProvider]] = {
        "binance": BinanceProvider,
        "alpaca": AlpacaProvider,
        "bybit": BybitProvider,
    }
    cls = registry.get(name.lower())
    if cls is None:
        available = ", ".join(registry.keys())
        raise ValueError(f"Unknown provider '{name}'. Available: {available}")
    return cls()
