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 Firearms:
    """Sync firearms resource."""

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

    # -- Collection endpoints --------------------------------------------------

    def list(self, params: Dict | None = None) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms", 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 search(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/search", query=params)

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

    def game_meta(self, params: Dict | None = None) -> APIResponse:
        return self._client.get("/v1/firearms/game-meta", query=params)

    def action_types(self) -> APIResponse:
        return self._client.get("/v1/firearms/action-types")

    def filter_options(self) -> APIResponse:
        return self._client.get("/v1/firearms/filter-options")

    def random(self, params: Dict | None = None) -> APIResponse:
        return self._client.get("/v1/firearms/random", query=params)

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

    def head_to_head(self, params: Dict) -> APIResponse:
        return self._client.get("/v1/firearms/head-to-head", query=params)

    def by_feature(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/by-feature", query=params)

    def by_action(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/by-action", query=params)

    def by_material(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/by-material", query=params)

    def by_designer(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/by-designer", query=params)

    def power_rating(self, params: Dict | None = None) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/power-rating", query=params)

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

    def by_conflict(self, params: Dict) -> PaginatedResponse:
        return self._client.get_paginated("/v1/firearms/by-conflict", query=params)

    # -- Single-resource endpoints ---------------------------------------------

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

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

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

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

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

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

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

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

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

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

    def get_silhouette(self, id: str, params: Dict | None = None) -> APIResponse:
        return self._client.get(f"/v1/firearms/{quote(id, safe='')}/silhouette", query=params)

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

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


class AsyncFirearms:
    """Async firearms resource."""

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

    # -- Collection endpoints --------------------------------------------------

    async def list(self, params: Dict | None = None) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms", 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 search(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/search", query=params)

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

    async def game_meta(self, params: Dict | None = None) -> APIResponse:
        return await self._client.get("/v1/firearms/game-meta", query=params)

    async def action_types(self) -> APIResponse:
        return await self._client.get("/v1/firearms/action-types")

    async def filter_options(self) -> APIResponse:
        return await self._client.get("/v1/firearms/filter-options")

    async def random(self, params: Dict | None = None) -> APIResponse:
        return await self._client.get("/v1/firearms/random", query=params)

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

    async def head_to_head(self, params: Dict) -> APIResponse:
        return await self._client.get("/v1/firearms/head-to-head", query=params)

    async def by_feature(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/by-feature", query=params)

    async def by_action(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/by-action", query=params)

    async def by_material(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/by-material", query=params)

    async def by_designer(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/by-designer", query=params)

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

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

    async def by_conflict(self, params: Dict) -> PaginatedResponse:
        return await self._client.get_paginated("/v1/firearms/by-conflict", query=params)

    # -- Single-resource endpoints ---------------------------------------------

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

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

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

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

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

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

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

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

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

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

    async def get_silhouette(self, id: str, params: Dict | None = None) -> APIResponse:
        return await self._client.get(
            f"/v1/firearms/{quote(id, safe='')}/silhouette", query=params
        )

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

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