"""Synchronous Ticksupply API client."""

from __future__ import annotations

from typing import Any

from ticksupply._base import ClientConfig, SyncHTTPClient
from ticksupply.resources.availability import AvailabilityResource
from ticksupply.resources.datastreams import DatastreamsResource
from ticksupply.resources.exchanges import ExchangesResource
from ticksupply.resources.exports import ExportsResource
from ticksupply.resources.subscriptions import SubscriptionsResource


class Client:
    """Synchronous 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 environment variable::

            >>> from ticksupply import Client
            >>>
            >>> # API key from TICKSUPPLY_API_KEY env var
            >>> client = Client()
            >>>
            >>> # List exchanges
            >>> for exchange in client.exchanges.list():
            ...     print(f"{exchange.code}: {exchange.display_name}")

        Using context manager::

            >>> with Client(api_key="key_xxx.secret") as client:
            ...     exchanges = client.exchanges.list()

        Creating a subscription::

            >>> # Find datastreams for binance BTCUSDT trades
            >>> result = client.exchanges.list_datastreams("binance", "BTCUSDT", stream_type="trade")
            >>> datastream_id = result.items[0].datastream_id
            >>>
            >>> # Create the subscription
            >>> sub = client.subscriptions.create(datastream_id)
            >>> print(f"Subscription ID: {sub.id}")

        Exporting data::

            >>> from datetime import datetime, timedelta, timezone
            >>>
            >>> # Create an export for the last 24 hours
            >>> end = datetime.now(timezone.utc)
            >>> start = end - timedelta(hours=24)
            >>> job = client.exports.create(datastream_id, start, end)
            >>>
            >>> # Wait for export to complete, then download
            >>> # (in practice, poll job.status until it's "succeeded")
            >>> download = client.exports.get_download(job.id)
            >>> print(f"Download URL: {download.url}")
    """

    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 = SyncHTTPClient(self._config)

        # Initialize resources
        self._exchanges = ExchangesResource(self._http_client)
        self._datastreams = DatastreamsResource(self._http_client)
        self._subscriptions = SubscriptionsResource(self._http_client)
        self._exports = ExportsResource(self._http_client)
        self._availability = AvailabilityResource(self._http_client)

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

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

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

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

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

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

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

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

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

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

    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 context manager pattern.
        """
        self._http_client.close()

    def __enter__(self) -> Client:
        """Enter context manager."""
        return self

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