"""Alpaca Markets OHLCV provider using the alpaca-py SDK."""

from __future__ import annotations

import asyncio
import logging
from datetime import date

from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
from alpaca.data.enums import Adjustment

from app.exceptions import ProviderError, RateLimitError
from app.providers.protocol import OHLCVData

logger = logging.getLogger(__name__)


class AlpacaOHLCVProvider:
    """Fetches daily OHLCV bars from Alpaca Markets Data API."""

    def __init__(self, api_key: str, api_secret: str) -> None:
        if not api_key or not api_secret:
            raise ProviderError("Alpaca API key and secret are required")
        self._client = StockHistoricalDataClient(api_key, api_secret)

    @staticmethod
    def _to_alpaca_symbol(symbol: str) -> str:
        """Convert internal symbol format (BRK-B) to Alpaca format (BRK.B)."""
        return symbol.replace("-", ".")

    @staticmethod
    def _from_alpaca_symbol(symbol: str) -> str:
        """Convert Alpaca symbol format (BRK.B) back to internal format (BRK-B)."""
        return symbol.replace(".", "-")

    async def fetch_ohlcv(
        self, ticker: str, start_date: date, end_date: date
    ) -> list[OHLCVData]:
        """Fetch daily OHLCV bars for *ticker* between *start_date* and *end_date*."""
        alpaca_symbol = self._to_alpaca_symbol(ticker)
        try:
            request = StockBarsRequest(
                symbol_or_symbols=alpaca_symbol,
                timeframe=TimeFrame.Day,
                start=start_date,
                end=end_date,
                adjustment=Adjustment.SPLIT,
            )

            # alpaca-py's client is synchronous — run in a thread
            bars = await asyncio.to_thread(self._client.get_stock_bars, request)

            results: list[OHLCVData] = []
            bar_set = bars.get(alpaca_symbol, []) if hasattr(bars, "get") else getattr(bars, "data", {}).get(alpaca_symbol, [])
            for bar in bar_set:
                results.append(
                    OHLCVData(
                        ticker=ticker,  # use original internal symbol
                        date=bar.timestamp.date(),
                        open=float(bar.open),
                        high=float(bar.high),
                        low=float(bar.low),
                        close=float(bar.close),
                        volume=int(bar.volume),
                    )
                )
            return results

        except Exception as exc:
            msg = str(exc).lower()
            if "rate" in msg and "limit" in msg:
                raise RateLimitError(f"Alpaca rate limit hit for {ticker}") from exc
            logger.error("Alpaca provider error for %s: %s", ticker, exc)
            raise ProviderError(f"Alpaca provider error for {ticker}: {exc}") from exc
