"""Exchange client protocol and base class.

All exchange-specific clients implement the :class:`ExchangeClient` Protocol.
This enables structural subtyping — any class with the right methods works,
without needing to explicitly inherit from a base class.
"""

from __future__ import annotations

from typing import Protocol, runtime_checkable, Any

from indiaopt.models.option_chain import OptionChainResult


@runtime_checkable
class ExchangeClient(Protocol):
    """Protocol defining the minimal interface for an exchange client.

    Any class implementing these methods is a valid exchange client, whether
    or not it subclasses :class:`BaseExchangeClient`.
    """

    async def fetch_option_chain(
        self,
        symbol: str,
        *,
        is_index: bool = True,
    ) -> OptionChainResult:
        """Fetch the full option chain for *symbol*.

        Args:
            symbol:   Trading symbol (e.g. ``"NIFTY"``).
            is_index: ``True`` for index instruments, ``False`` for equities.

        Returns:
            :class:`~indiaopt.models.option_chain.OptionChainResult`
        """
        ...

    async def fetch_raw_option_chain(
        self,
        symbol: str,
        *,
        is_index: bool = True,
        expiry: str | None = None,
    ) -> dict[str, Any]:
        """Fetch the unparsed raw JSON dictionary from the exchange."""
        ...

    async def get_expiry_dates(self, symbol: str) -> list[str]:
        """Return available expiry date strings for *symbol*.

        Returns:
            List of expiry date strings in exchange-specific format.
        """
        ...

    async def __aenter__(self) -> ExchangeClient:
        ...

    async def __aexit__(self, *args: object) -> None:
        ...


__all__ = ["ExchangeClient"]
