"""Async Duffel client class that wires up all async resource groups."""

from functools import cached_property

import httpx

from ._base import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, AsyncHttpTransport
from .resources.airline_credits import AsyncAirlineCredits
from .resources.airline_initiated_changes import AsyncAirlineInitiatedChanges
from .resources.batch_offer_requests import AsyncBatchOfferRequests
from .resources.cards import AsyncCards
from .resources.identity import AsyncComponentClientKeys, AsyncCustomerUserGroups, AsyncCustomerUsers
from .resources.offer_requests import AsyncOfferRequests
from .resources.offers import AsyncOffers
from .resources.order_cancellations import AsyncOrderCancellations
from .resources.order_changes import AsyncOrderChangeOffers, AsyncOrderChangeRequests, AsyncOrderChanges
from .resources.orders import AsyncOrders
from .resources.partial_offer_requests import AsyncPartialOfferRequests
from .resources.payments import AsyncPayments
from .resources.seat_maps import AsyncSeatMaps
from .resources.stays import (
    AsyncAccommodation,
    AsyncAccommodationLoyaltyProgrammes,
    AsyncNegotiatedRates,
    AsyncStaysBookings,
    AsyncStaysBrands,
    AsyncStaysQuotes,
    AsyncStaysSearch,
    AsyncStaysSearchResults,
)
from .resources.supporting import (
    AsyncAircraftResource,
    AsyncAirlines,
    AsyncAirports,
    AsyncCities,
    AsyncLoyaltyProgrammes,
    AsyncPlaces,
)
from .resources.three_d_secure import AsyncThreeDSecureSessions
from .resources.webhooks import AsyncWebhookDeliveries, AsyncWebhookEvents, AsyncWebhooks


class AsyncDuffel:
    """Async client for the Duffel API.

    Usage::

        async with AsyncDuffel(token="duffel_test_...") as client:
            offer_req = await client.offer_requests.create(
                slices=[{"origin": "LHR", "destination": "JFK", "departure_date": "2026-06-01"}],
                passengers=[{"type": "adult"}],
            )

            async for offer in client.offers.list(offer_req.id):
                print(offer.total_amount, offer.owner.name)
    """

    def __init__(
        self,
        token: str,
        *,
        base_url: str = DEFAULT_BASE_URL,
        timeout: float = DEFAULT_TIMEOUT,
        http_client: httpx.AsyncClient | None = None,
    ):
        self._transport = AsyncHttpTransport(
            token=token, base_url=base_url, timeout=timeout, http_client=http_client,
        )

    async def close(self) -> None:
        """Close the underlying async HTTP connection pool."""
        await self._transport.close()

    async def __aenter__(self) -> "AsyncDuffel":
        return self

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

    # --- Flights ---

    @cached_property
    def offer_requests(self) -> AsyncOfferRequests:
        return AsyncOfferRequests(self._transport)

    @cached_property
    def offers(self) -> AsyncOffers:
        return AsyncOffers(self._transport)

    @cached_property
    def orders(self) -> AsyncOrders:
        return AsyncOrders(self._transport)

    @cached_property
    def payments(self) -> AsyncPayments:
        return AsyncPayments(self._transport)

    @cached_property
    def seat_maps(self) -> AsyncSeatMaps:
        return AsyncSeatMaps(self._transport)

    @cached_property
    def order_cancellations(self) -> AsyncOrderCancellations:
        return AsyncOrderCancellations(self._transport)

    @cached_property
    def order_change_requests(self) -> AsyncOrderChangeRequests:
        return AsyncOrderChangeRequests(self._transport)

    @cached_property
    def order_change_offers(self) -> AsyncOrderChangeOffers:
        return AsyncOrderChangeOffers(self._transport)

    @cached_property
    def order_changes(self) -> AsyncOrderChanges:
        return AsyncOrderChanges(self._transport)

    @cached_property
    def partial_offer_requests(self) -> AsyncPartialOfferRequests:
        return AsyncPartialOfferRequests(self._transport)

    @cached_property
    def airline_initiated_changes(self) -> AsyncAirlineInitiatedChanges:
        return AsyncAirlineInitiatedChanges(self._transport)

    @cached_property
    def batch_offer_requests(self) -> AsyncBatchOfferRequests:
        return AsyncBatchOfferRequests(self._transport)

    @cached_property
    def airline_credits(self) -> AsyncAirlineCredits:
        return AsyncAirlineCredits(self._transport)

    # --- Stays ---

    @cached_property
    def stays_search(self) -> AsyncStaysSearch:
        return AsyncStaysSearch(self._transport)

    @cached_property
    def stays_search_results(self) -> AsyncStaysSearchResults:
        return AsyncStaysSearchResults(self._transport)

    @cached_property
    def stays_quotes(self) -> AsyncStaysQuotes:
        return AsyncStaysQuotes(self._transport)

    @cached_property
    def stays_bookings(self) -> AsyncStaysBookings:
        return AsyncStaysBookings(self._transport)

    @cached_property
    def accommodation(self) -> AsyncAccommodation:
        return AsyncAccommodation(self._transport)

    @cached_property
    def negotiated_rates(self) -> AsyncNegotiatedRates:
        return AsyncNegotiatedRates(self._transport)

    @cached_property
    def stays_brands(self) -> AsyncStaysBrands:
        return AsyncStaysBrands(self._transport)

    @cached_property
    def accommodation_loyalty_programmes(self) -> AsyncAccommodationLoyaltyProgrammes:
        return AsyncAccommodationLoyaltyProgrammes(self._transport)

    # --- Payments ---

    @cached_property
    def cards(self) -> AsyncCards:
        return AsyncCards(self._transport)

    @cached_property
    def three_d_secure_sessions(self) -> AsyncThreeDSecureSessions:
        return AsyncThreeDSecureSessions(self._transport)

    # --- Notifications ---

    @cached_property
    def webhooks(self) -> AsyncWebhooks:
        return AsyncWebhooks(self._transport)

    @cached_property
    def webhook_deliveries(self) -> AsyncWebhookDeliveries:
        return AsyncWebhookDeliveries(self._transport)

    @cached_property
    def webhook_events(self) -> AsyncWebhookEvents:
        return AsyncWebhookEvents(self._transport)

    # --- Identity ---

    @cached_property
    def customer_users(self) -> AsyncCustomerUsers:
        return AsyncCustomerUsers(self._transport)

    @cached_property
    def customer_user_groups(self) -> AsyncCustomerUserGroups:
        return AsyncCustomerUserGroups(self._transport)

    @cached_property
    def component_client_keys(self) -> AsyncComponentClientKeys:
        return AsyncComponentClientKeys(self._transport)

    # --- Supporting Resources ---

    @cached_property
    def airlines(self) -> AsyncAirlines:
        return AsyncAirlines(self._transport)

    @cached_property
    def aircraft(self) -> AsyncAircraftResource:
        return AsyncAircraftResource(self._transport)

    @cached_property
    def airports(self) -> AsyncAirports:
        return AsyncAirports(self._transport)

    @cached_property
    def cities(self) -> AsyncCities:
        return AsyncCities(self._transport)

    @cached_property
    def places(self) -> AsyncPlaces:
        return AsyncPlaces(self._transport)

    @cached_property
    def loyalty_programmes(self) -> AsyncLoyaltyProgrammes:
        return AsyncLoyaltyProgrammes(self._transport)
