"""Technicals scraper for fetching technical analysis indicators."""

import logging
import re
from typing import Any

from tv_scraper.core.base import BaseScraper
from tv_scraper.core.constants import SCANNER_URL
from tv_scraper.core.exceptions import NetworkError, ValidationError

logger = logging.getLogger(__name__)


class Technicals(BaseScraper):
    """Scraper for technical analysis indicators from TradingView.

    Fetches indicator values (RSI, MACD, EMA, etc.) for a given symbol
    via the TradingView scanner API.

    Args:
        export_result: Whether to export results to file.
        export_type: Export format, ``"json"`` or ``"csv"``.
        timeout: HTTP request timeout in seconds.

    Example::

        from tv_scraper.scrapers.market_data import Technicals

        scraper = Technicals()
        data = scraper.get_technicals(
            exchange="BINANCE",
            symbol="BTCUSD",
            technical_indicators=["RSI", "Stoch.K"],
        )
    """

    def get_technicals(
        self,
        exchange: str,
        symbol: str,
        timeframe: str = "1d",
        technical_indicators: list[str] | None = None,
        all_indicators: bool = False,
        fields: list[str] | None = None,
    ) -> dict[str, Any]:
        """Scrape technical indicator values for a symbol.

        Args:
            exchange: Exchange name (e.g. ``"BINANCE"``).
            symbol: Trading symbol slug (e.g. ``"NIFTY"``).
            timeframe: Timeframe string (e.g. ``"1d"``, ``"4h"``, ``"1w"``).
            technical_indicators: List of indicator names to fetch.
                Required unless ``all_indicators=True``.
            all_indicators: If ``True``, fetch all known indicators.
            fields: Optional list of indicator names to include in the
                output (post-fetch filtering).

        Returns:
            Standardized response dict with keys
            ``status``, ``data``, ``metadata``, ``error``.
        """

        # --- Validation ---
        try:
            self.validator.verify_symbol_exchange(exchange, symbol)
            self.validator.validate_timeframe(timeframe)
        except ValidationError as exc:
            return self._error_response(str(exc))

        # Resolve indicator list
        if all_indicators:
            indicators = self.validator.get_indicators()
        elif technical_indicators:
            try:
                self.validator.validate_indicators(technical_indicators)
            except ValidationError as exc:
                return self._error_response(str(exc))
            indicators = list(technical_indicators)
        else:
            return self._error_response(
                "No indicators provided. "
                "Use technical_indicators or set all_indicators=True."
            )

        # --- Build API request ---
        timeframes = self.validator.get_timeframes()
        timeframe_value: str = timeframes.get(timeframe, "")

        if timeframe_value:
            api_indicators = [f"{ind}|{timeframe_value}" for ind in indicators]
        else:
            api_indicators = list(indicators)

        # Build query parameters for GET request
        fields_param = ",".join(api_indicators)

        params: dict[str, str] = {
            "symbol": f"{exchange}:{symbol}",
            "fields": fields_param,
            "no_404": "true",
        }

        url = f"{SCANNER_URL}/symbol"

        # --- Execute request ---
        try:
            response = self._make_request(url, method="GET", params=params)
            json_response: dict[str, Any] = response.json()
        except NetworkError as exc:
            return self._error_response(str(exc))
        except (ValueError, KeyError) as exc:
            return self._error_response(f"Failed to parse API response: {exc}")

        # --- Parse response ---
        # API returns indicators directly as a dict, not wrapped in "data"
        if not json_response:
            return self._error_response("No data returned from API.")

        result: dict[str, Any] = {}
        # Map requested indicators to response values
        for ind in api_indicators:
            result[ind] = json_response.get(ind)

        # Strip timeframe suffix from keys
        result = self._revise_response(result, timeframe_value)

        # Optional field filtering
        if fields:
            result = {k: v for k, v in result.items() if k in fields}

        # --- Export ---
        if self.export_result:
            self._export(
                data=result,
                symbol=symbol,
                data_category="technicals",
                timeframe=timeframe,
            )

        return self._success_response(
            result,
            exchange=exchange,
            symbol=symbol,
            timeframe=timeframe,
        )

    def _revise_response(
        self, data: dict[str, Any], timeframe_value: str
    ) -> dict[str, Any]:
        """Clean indicator key names by stripping timeframe suffixes.

        Args:
            data: Dict with indicator names as keys.
            timeframe_value: The timeframe suffix that was appended
                (e.g. ``"240"`` for 4h). Empty string for daily.

        Returns:
            Dict with cleaned keys (``|suffix`` removed).
        """
        if not timeframe_value:
            return data
        return {re.sub(r"\|.*", "", k): v for k, v in data.items()}
