"""Asynchronous Ticksupply API client."""

from __future__ import annotations

from typing import Any

from ticksupply._base import AsyncHTTPClient, ClientConfig
from ticksupply.resources.availability import AsyncAvailabilityResource
from ticksupply.resources.datastreams import AsyncDatastreamsResource
from ticksupply.resources.exchanges import AsyncExchangesResource
from ticksupply.resources.exports import AsyncExportsResource
from ticksupply.resources.subscriptions import AsyncSubscriptionsResource


class AsyncClient:
    """Asynchronous client for the Ticksupply API.

    The client provides access to market data subscriptions and exports
    through resource-based namespaces.

    Args:
        api_key: API key for authentication. If not provided, reads from
            TICKSUPPLY_API_KEY environment variable.
        base_url: Base URL for the API. Defaults to https://api.ticksupply.com/v1.
        timeout: Request timeout in seconds. Defaults to 30.
        max_retries: Maximum number of retries for failed requests. Defaults to 3.

    Example:
        Basic usage with async context manager::

            >>> import asyncio
            >>> from ticksupply import AsyncClient
            >>>
            >>> async def main():
            ...     async with AsyncClient() as client:
            ...         # List exchanges
            ...         exchanges = await client.exchanges.list()
            ...         for exchange in exchanges:
            ...             print(f"{exchange.code}: {exchange.display_name}")
            >>>
            >>> asyncio.run(main())

        Creating a subscription::

            >>> async with AsyncClient(api_key="key_xxx.secret") as client:
            ...     # Find the variant for binance BTCUSDT trades
            ...     ds = await client.exchanges.get_datastream("binance", "BTCUSDT", "trades")
            ...     variant_id = ds.variants[0].variant_id
            ...
            ...     # Create the subscription
            ...     sub = await client.subscriptions.create(variant_id)
            ...     print(f"Subscription ID: {sub.id}")

        Iterating with async for::

            >>> async with AsyncClient() as client:
            ...     async for sub in client.subscriptions.list_all():
            ...         print(f"{sub.id}: {sub.status}")
    """

    def __init__(
        self,
        api_key: str | None = None,
        *,
        base_url: str | None = None,
        timeout: float | None = None,
        max_retries: int | None = None,
    ) -> None:
        # Build config with defaults
        config_kwargs: dict[str, Any] = {}
        if api_key is not None:
            config_kwargs["api_key"] = api_key
        if base_url is not None:
            config_kwargs["base_url"] = base_url
        if timeout is not None:
            config_kwargs["timeout"] = timeout
        if max_retries is not None:
            config_kwargs["max_retries"] = max_retries

        self._config = ClientConfig(**config_kwargs)
        self._http_client = AsyncHTTPClient(self._config)

        # Initialize resources
        self._exchanges = AsyncExchangesResource(self._http_client)
        self._datastreams = AsyncDatastreamsResource(self._http_client)
        self._subscriptions = AsyncSubscriptionsResource(self._http_client)
        self._exports = AsyncExportsResource(self._http_client)
        self._availability = AsyncAvailabilityResource(self._http_client)

    @property
    def exchanges(self) -> AsyncExchangesResource:
        """Access exchange and catalog operations.

        Provides methods to list exchanges, instruments, and datastreams.
        """
        return self._exchanges

    @property
    def datastreams(self) -> AsyncDatastreamsResource:
        """Access datastream catalog operations.

        Provides methods to list and filter available datastreams
        across all exchanges and instruments.
        """
        return self._datastreams

    @property
    def subscriptions(self) -> AsyncSubscriptionsResource:
        """Access subscription operations.

        Provides methods to create, list, pause, resume, and delete
        data stream subscriptions.
        """
        return self._subscriptions

    @property
    def exports(self) -> AsyncExportsResource:
        """Access export operations.

        Provides methods to create, list, and download historical
        data exports.
        """
        return self._exports

    @property
    def availability(self) -> AsyncAvailabilityResource:
        """Access data availability queries.

        Provides methods to check what data is available for
        specific datastreams.
        """
        return self._availability

    async def close(self) -> None:
        """Close the client and release resources.

        This should be called when you're done using the client,
        unless you're using the async context manager pattern.
        """
        await self._http_client.close()

    async def __aenter__(self) -> AsyncClient:
        """Enter async context manager."""
        return self

    async def __aexit__(self, *args: Any) -> None:
        """Exit async context manager and close resources."""
        await self.close()
