from __future__ import annotations

from typing import TYPE_CHECKING, AsyncIterator, Dict, Iterator
from urllib.parse import quote

if TYPE_CHECKING:
    from .._core._http_client import APIResponse, AsyncHttpClient, PaginatedResponse, SyncHttpClient


class Calibers:
    """Sync calibers resource."""

    def __init__(self, client: SyncHttpClient) -> None:
        self._client = client

    def list(self, params: Dict | None = None) -> PaginatedResponse:
        return self._client.get_paginated("/v1/calibers", query=params)

    def list_auto_paging(self, params: Dict | None = None) -> Iterator:
        page = (params or {}).get("page", 1)
        while True:
            result = self.list({**(params or {}), "page": page})
            yield from result.data
            if not result.pagination.total_pages or page >= result.pagination.total_pages:
                break
            page += 1

    def compare(self, params: Dict) -> APIResponse:
        return self._client.get("/v1/calibers/compare", query=params)

    def ballistics(self, params: Dict) -> APIResponse:
        return self._client.get("/v1/calibers/ballistics", query=params)

    def get(self, id: str) -> APIResponse:
        return self._client.get(f"/v1/calibers/{quote(id, safe='')}")

    def get_firearms(self, id: str, params: Dict | None = None) -> PaginatedResponse:
        return self._client.get_paginated(
            f"/v1/calibers/{quote(id, safe='')}/firearms", query=params
        )

    def get_parent_chain(self, id: str) -> APIResponse:
        return self._client.get(f"/v1/calibers/{quote(id, safe='')}/parent-chain")

    def get_family(self, id: str) -> APIResponse:
        return self._client.get(f"/v1/calibers/{quote(id, safe='')}/family")

    def get_ammunition(self, id: str, params: Dict | None = None) -> PaginatedResponse:
        return self._client.get_paginated(
            f"/v1/calibers/{quote(id, safe='')}/ammunition", query=params
        )


class AsyncCalibers:
    """Async calibers resource."""

    def __init__(self, client: AsyncHttpClient) -> None:
        self._client = client

    async def list(self, params: Dict | None = None) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/calibers", query=params)

    async def list_auto_paging(self, params: Dict | None = None) -> AsyncIterator:
        page = (params or {}).get("page", 1)
        while True:
            result = await self.list({**(params or {}), "page": page})
            for item in result.data:
                yield item
            if not result.pagination.total_pages or page >= result.pagination.total_pages:
                break
            page += 1

    async def compare(self, params: Dict) -> APIResponse:
        return await self._client.get("/v1/calibers/compare", query=params)

    async def ballistics(self, params: Dict) -> APIResponse:
        return await self._client.get("/v1/calibers/ballistics", query=params)

    async def get(self, id: str) -> APIResponse:
        return await self._client.get(f"/v1/calibers/{quote(id, safe='')}")

    async def get_firearms(self, id: str, params: Dict | None = None) -> PaginatedResponse:
        return await self._client.get_paginated(
            f"/v1/calibers/{quote(id, safe='')}/firearms", query=params
        )

    async def get_parent_chain(self, id: str) -> APIResponse:
        return await self._client.get(f"/v1/calibers/{quote(id, safe='')}/parent-chain")

    async def get_family(self, id: str) -> APIResponse:
        return await self._client.get(f"/v1/calibers/{quote(id, safe='')}/family")

    async def get_ammunition(self, id: str, params: Dict | None = None) -> PaginatedResponse:
        return await self._client.get_paginated(
            f"/v1/calibers/{quote(id, safe='')}/ammunition", query=params
        )
