from typing import Any

from .._base import (
    LONG_TIMEOUT,
    AsyncBaseResource,
    AsyncPageIterator,
    BaseResource,
    PageIterator,
    unwrap_data,
    unwrap_response,
)
from ..models import Order, Service


class Orders(BaseResource):
    _path = "/air/orders"

    def list(
        self,
        *,
        limit: int | None = None,
        booking_reference: str | None = None,
        offer_id: str | None = None,
        awaiting_payment: bool | None = None,
        sort: str | None = None,
        requires_action: bool | None = None,
        user_id: str | None = None,
    ) -> PageIterator[Order]:
        return self._list(
            Order,
            params={
                "limit": limit,
                "booking_reference": booking_reference,
                "offer_id": offer_id,
                "awaiting_payment": awaiting_payment,
                "sort": sort,
                "requires_action": requires_action,
                "user_id": user_id,
            },
        )

    def get(self, id: str) -> Order:
        return self._get(id, Order)

    def create(
        self,
        *,
        selected_offers: "list[str]",
        passengers: "list[dict[str, Any]]",
        type: str | None = None,
        payments: "list[dict[str, Any]] | None" = None,
        services: "list[dict[str, Any]] | None" = None,
        users: "list[str] | None" = None,
        metadata: dict[str, str] | None = None,
    ) -> Order:
        data: dict[str, Any] = {
            "selected_offers": selected_offers,
            "passengers": passengers,
        }
        if type is not None:
            data["type"] = type
        if payments is not None:
            data["payments"] = payments
        if services is not None:
            data["services"] = services
        if users is not None:
            data["users"] = users
        if metadata is not None:
            data["metadata"] = metadata

        return self._create(Order, data, timeout=LONG_TIMEOUT)

    def update(self, id: str, *, metadata: dict[str, str] | None = None) -> Order:
        data: dict[str, Any] = {}
        if metadata is not None:
            data["metadata"] = metadata
        return self._update(id, Order, data)

    def available_services(self, id: str) -> "list[Service]":
        resp = self._transport.request("GET", f"{self._path}/{id}/available_services")
        body = unwrap_response(resp)
        return [Service.model_validate(s) for s in body.get("data", [])]

    def add_service(self, id: str, *, service_id: str, quantity: int) -> Order:
        resp = self._transport.request(
            "POST",
            f"{self._path}/{id}/services",
            json_body={"data": {"id": service_id, "quantity": quantity}},
        )
        return unwrap_data(resp, Order)


class AsyncOrders(AsyncBaseResource):
    _path = "/air/orders"

    def list(
        self,
        *,
        limit: int | None = None,
        booking_reference: str | None = None,
        offer_id: str | None = None,
        awaiting_payment: bool | None = None,
        sort: str | None = None,
        requires_action: bool | None = None,
        user_id: str | None = None,
    ) -> AsyncPageIterator[Order]:
        return self._list(
            Order,
            params={
                "limit": limit,
                "booking_reference": booking_reference,
                "offer_id": offer_id,
                "awaiting_payment": awaiting_payment,
                "sort": sort,
                "requires_action": requires_action,
                "user_id": user_id,
            },
        )

    async def get(self, id: str) -> Order:
        return await self._get(id, Order)

    async def create(
        self,
        *,
        selected_offers: "list[str]",
        passengers: "list[dict[str, Any]]",
        type: str | None = None,
        payments: "list[dict[str, Any]] | None" = None,
        services: "list[dict[str, Any]] | None" = None,
        users: "list[str] | None" = None,
        metadata: dict[str, str] | None = None,
    ) -> Order:
        data: dict[str, Any] = {
            "selected_offers": selected_offers,
            "passengers": passengers,
        }
        if type is not None:
            data["type"] = type
        if payments is not None:
            data["payments"] = payments
        if services is not None:
            data["services"] = services
        if users is not None:
            data["users"] = users
        if metadata is not None:
            data["metadata"] = metadata

        return await self._create(Order, data, timeout=LONG_TIMEOUT)

    async def update(self, id: str, *, metadata: dict[str, str] | None = None) -> Order:
        data: dict[str, Any] = {}
        if metadata is not None:
            data["metadata"] = metadata
        return await self._update(id, Order, data)

    async def available_services(self, id: str) -> "list[Service]":
        resp = await self._transport.request("GET", f"{self._path}/{id}/available_services")
        body = unwrap_response(resp)
        return [Service.model_validate(s) for s in body.get("data", [])]

    async def add_service(self, id: str, *, service_id: str, quantity: int) -> Order:
        resp = await self._transport.request(
            "POST",
            f"{self._path}/{id}/services",
            json_body={"data": {"id": service_id, "quantity": quantity}},
        )
        return unwrap_data(resp, Order)
