"""Main Duffel client class that wires up all resource groups."""

from functools import cached_property

import httpx

from ._base import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, HttpTransport
from .resources.airline_credits import AirlineCredits
from .resources.airline_initiated_changes import AirlineInitiatedChanges
from .resources.batch_offer_requests import BatchOfferRequests
from .resources.cards import Cards
from .resources.identity import ComponentClientKeys, CustomerUserGroups, CustomerUsers
from .resources.offer_requests import OfferRequests
from .resources.offers import Offers
from .resources.order_cancellations import OrderCancellations
from .resources.order_changes import OrderChangeOffers, OrderChangeRequests, OrderChanges
from .resources.orders import Orders
from .resources.partial_offer_requests import PartialOfferRequests
from .resources.payments import Payments
from .resources.seat_maps import SeatMaps
from .resources.stays import (
    Accommodation,
    AccommodationLoyaltyProgrammes,
    NegotiatedRates,
    StaysBookings,
    StaysBrands,
    StaysQuotes,
    StaysSearch,
    StaysSearchResults,
)
from .resources.supporting import (
    AircraftResource,
    Airlines,
    Airports,
    Cities,
    LoyaltyProgrammes,
    Places,
)
from .resources.three_d_secure import ThreeDSecureSessions
from .resources.webhooks import WebhookDeliveries, WebhookEvents, Webhooks


class Duffel:
    """Synchronous client for the Duffel API.

    Usage::

        client = Duffel(token="duffel_test_...")

        # Search flights
        offer_req = client.offer_requests.create(
            slices=[{"origin": "LHR", "destination": "JFK", "departure_date": "2026-06-01"}],
            passengers=[{"type": "adult"}],
        )

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

        client.close()
    """

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

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

    def __enter__(self) -> "Duffel":
        return self

    def __exit__(self, *args) -> None:
        self.close()

    # --- Flights ---

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

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

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

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

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

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

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

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

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

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

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

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

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

    # --- Stays ---

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

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

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

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

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

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

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

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

    # --- Payments ---

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

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

    # --- Notifications ---

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

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

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

    # --- Identity ---

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

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

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

    # --- Supporting Resources ---

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

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

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

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

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

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