from typing import Any

from .._base import AsyncBaseResource, AsyncPageIterator, BaseResource, PageIterator, unwrap_response
from ..models import Aircraft, Airline, Airport, City, LoyaltyProgramme, Place


class Airlines(BaseResource):
    _path = "/air/airlines"

    def list(self, *, limit: int | None = None) -> PageIterator[Airline]:
        return self._list(Airline, params={"limit": limit})

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


class AircraftResource(BaseResource):
    _path = "/air/aircraft"

    def list(self, *, limit: int | None = None) -> PageIterator[Aircraft]:
        return self._list(Aircraft, params={"limit": limit})

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


class Airports(BaseResource):
    _path = "/air/airports"

    def list(
        self, *, limit: int | None = None, iata_country_code: str | None = None,
    ) -> PageIterator[Airport]:
        return self._list(Airport, params={"limit": limit, "iata_country_code": iata_country_code})

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


class Cities(BaseResource):
    _path = "/air/cities"

    def list(self, *, limit: int | None = None) -> PageIterator[City]:
        return self._list(City, params={"limit": limit})

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


class Places(BaseResource):
    _path = "/places/suggestions"

    def suggest(
        self,
        query: str,
        *,
        lat: str | None = None,
        lng: str | None = None,
        rad: str | None = None,
    ) -> list[Place]:
        params: dict[str, Any] = {"query": query}
        if lat is not None:
            params["lat"] = lat
        if lng is not None:
            params["lng"] = lng
        if rad is not None:
            params["rad"] = rad
        resp = self._transport.request("GET", self._path, params=params)
        body = unwrap_response(resp)
        return [Place.model_validate(p) for p in body.get("data", [])]


class LoyaltyProgrammes(BaseResource):
    _path = "/air/loyalty_programmes"

    def list(self, *, limit: int | None = None) -> PageIterator[LoyaltyProgramme]:
        return self._list(LoyaltyProgramme, params={"limit": limit})

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


class AsyncAirlines(AsyncBaseResource):
    _path = "/air/airlines"

    def list(self, *, limit: int | None = None) -> AsyncPageIterator[Airline]:
        return self._list(Airline, params={"limit": limit})

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


class AsyncAircraftResource(AsyncBaseResource):
    _path = "/air/aircraft"

    def list(self, *, limit: int | None = None) -> AsyncPageIterator[Aircraft]:
        return self._list(Aircraft, params={"limit": limit})

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


class AsyncAirports(AsyncBaseResource):
    _path = "/air/airports"

    def list(
        self, *, limit: int | None = None, iata_country_code: str | None = None,
    ) -> AsyncPageIterator[Airport]:
        return self._list(Airport, params={"limit": limit, "iata_country_code": iata_country_code})

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


class AsyncCities(AsyncBaseResource):
    _path = "/air/cities"

    def list(self, *, limit: int | None = None) -> AsyncPageIterator[City]:
        return self._list(City, params={"limit": limit})

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


class AsyncPlaces(AsyncBaseResource):
    _path = "/places/suggestions"

    async def suggest(
        self,
        query: str,
        *,
        lat: str | None = None,
        lng: str | None = None,
        rad: str | None = None,
    ) -> list[Place]:
        params: dict[str, Any] = {"query": query}
        if lat is not None:
            params["lat"] = lat
        if lng is not None:
            params["lng"] = lng
        if rad is not None:
            params["rad"] = rad
        resp = await self._transport.request("GET", self._path, params=params)
        body = unwrap_response(resp)
        return [Place.model_validate(p) for p in body.get("data", [])]


class AsyncLoyaltyProgrammes(AsyncBaseResource):
    _path = "/air/loyalty_programmes"

    def list(self, *, limit: int | None = None) -> AsyncPageIterator[LoyaltyProgramme]:
        return self._list(LoyaltyProgramme, params={"limit": limit})

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