# app/src/market_data/acquisition/adapters/dzengi/rest.py

from __future__ import annotations

from typing import Protocol

from src.integrations.exchange.rest_client import ExchangeRestClient
from src.market_data.acquisition.exceptions import (
    CandleTransportError,
    InstrumentReferenceTransportError,
    QuoteTransportError,
)


_EXCHANGE_INFO_PATH = "/api/v1/exchangeInfo"
_TICKER_24HR_PATH = "/api/v1/ticker/24hr"
_KLINES_PATH = "/api/v1/klines"


# Минимальный транспортный контракт, необходимый Dzengi REST adapter.
class _PayloadRestClient(Protocol):
    def get_payload(
        self,
        path: str,
        params: dict[str, str] | None = None,
        headers: dict[str, str] | None = None,
    ) -> object:
        ...


class DzengiInstrumentDocumentSource:
    """
    Источник сырого документа Instrument Reference Data через Dzengi REST API.

    На переходном этапе использует legacy ExchangeRestClient.
    Зависимость должна быть удалена после появления общего transport-клиента
    или после полного вывода integrations/exchange из эксплуатации.
    """

    def __init__(
        self,
        client: _PayloadRestClient | None = None,
    ) -> None:
        self._client = client

    def fetch_instrument_document(self) -> object:
        """
        Получить декодированный ответ Dzengi exchangeInfo без его обработки.

        Метод не выполняет schema validation, parsing, value validation,
        mapping или кэширование.
        """

        try:
            client: _PayloadRestClient = (
                self._client
                if self._client is not None
                else ExchangeRestClient()
            )

            return client.get_payload(_EXCHANGE_INFO_PATH)

        except Exception as exc:
            raise InstrumentReferenceTransportError(
                "Не удалось получить Instrument Reference Data "
                f"от Dzengi: {exc}"
            ) from exc


class DzengiQuoteDocumentSource:
    """Источник сырого документа текущей котировки через Dzengi REST API."""

    def __init__(
        self,
        client: _PayloadRestClient | None = None,
    ) -> None:
        self._client = client

    def fetch_quote_document(
        self,
        symbol: str,
    ) -> object:
        """
        Получить декодированный ответ Dzengi ticker/24hr без его обработки.

        Метод не выполняет нормализацию symbol, schema validation, parsing,
        value validation, mapping, retry или кэширование.
        """

        try:
            client: _PayloadRestClient = (
                self._client
                if self._client is not None
                else ExchangeRestClient()
            )

            return client.get_payload(
                _TICKER_24HR_PATH,
                params={
                    "symbol": symbol,
                },
            )

        except Exception as exc:
            raise QuoteTransportError(
                "Не удалось получить текущую котировку "
                f"от Dzengi для символа '{symbol}': {exc}"
            ) from exc


class DzengiCandlesDocumentSource:
    """Источник сырого документа свечей через Dzengi REST API."""

    def __init__(
        self,
        client: _PayloadRestClient | None = None,
    ) -> None:
        self._client = client

    def fetch_candles_document(
        self,
        symbol: str,
        *,
        interval: str,
        limit: int,
        price_type: str,
    ) -> object:
        """
        Получить декодированный ответ Dzengi klines без его обработки.

        Метод не выполняет нормализацию параметров запроса, schema validation,
        parsing, value validation, mapping, retry, сортировку или кэширование.
        """

        try:
            client: _PayloadRestClient = (
                self._client
                if self._client is not None
                else ExchangeRestClient()
            )

            return client.get_payload(
                _KLINES_PATH,
                params={
                    "symbol": symbol,
                    "interval": interval,
                    "limit": str(limit),
                    "priceType": price_type,
                },
            )

        except Exception as exc:
            raise CandleTransportError(
                "Не удалось получить свечи "
                f"от Dzengi для символа '{symbol}', "
                f"интервала '{interval}' и типа цены '{price_type}': {exc}"
            ) from exc