"""Polling-based fallback stream when SSE is unavailable."""

from __future__ import annotations

import time
from typing import Any, Callable, Generator, Optional

import httpx

from sd_api.config import settings
from sd_api.logging import get_logger
from sd_api.models.quote import Quote, QuoteSnapshot
from sd_api.stream.sse import SSEClient

logger = get_logger("stream.poller")


class PollerClient:
    """HTTP polling wrapper that mimics the SSE interface.

    Use this as a fallback when SSE connections are blocked (e.g. corporate proxies).

    Usage::

        poller = PollerClient("http://127.0.0.1:5000", symbol="XAUUSD")
        for quote in poller.poll_quote():
            print(quote)
    """

    def __init__(
        self,
        base_url: str,
        *,
        interval: float | None = None,
        timeout: float = 30.0,
    ) -> None:
        self.base_url = base_url.rstrip("/")
        self.interval = interval or settings.poll_interval
        self.timeout = timeout
        self._client = httpx.Client(timeout=self.timeout)

    def close(self) -> None:
        self._client.close()

    # ── Polling generators ─────────────────────────────────────────────────

    def poll_quote(self, symbol: str) -> Generator[Quote, None, None]:
        """Continuously poll GET /api/quote-live for a single symbol.

        Stops when the generator is garbage-collected or interrupted.
        """
        symbol = symbol.upper().strip()
        while True:
            try:
                resp = self._client.get(
                    f"{self.base_url}/api/quote-live",
                    params={"symbol": symbol},
                )
                if resp.status_code == 200:
                    payload = resp.json()
                    yield Quote.from_api(payload)
                else:
                    logger.warning(f"poll_quote got {resp.status_code}")
            except httpx.HTTPError as e:
                logger.warning(f"poll_quote error: {e}")
            time.sleep(self.interval)

    def poll_quotes(
        self,
        symbols: Optional[str] = None,
    ) -> Generator[QuoteSnapshot, None, None]:
        """Continuously poll GET /api/quotes-live for the full market snapshot."""
        symbols_upper = symbols.upper().strip() if symbols else None
        while True:
            try:
                params = {"symbols": symbols_upper} if symbols_upper else None
                resp = self._client.get(
                    f"{self.base_url}/api/quotes-live",
                    params=params,
                )
                if resp.status_code == 200:
                    payload = resp.json()
                    yield QuoteSnapshot.from_api(payload)
                else:
                    logger.warning(f"poll_quotes got {resp.status_code}")
            except httpx.HTTPError as e:
                logger.warning(f"poll_quotes error: {e}")
            time.sleep(self.interval)

    def __enter__(self) -> "PollerClient":
        return self

    def __exit__(self, *_: Any) -> None:
        self.close()
