from __future__ import annotations

from typing import TYPE_CHECKING, Any, Literal

from ..._endpoints import Search
from ..._internal._builders.search import build_search_body
from ..._internal._schemas import APIEnvelope
from ..._internal._schemas.search import SearchResult
from .._base import BaseResource

if TYPE_CHECKING:
    from ..._sync_client import SyncClient
else:
    SyncClient = Any


class SearchResource(BaseResource[SyncClient]):
    """Searches the SeaArt platform across various content types (sync).

    Accessible via ``client.search``.

    The convenience methods (``works``, ``models``, ``characters``, etc.)
    are thin wrappers around :meth:`all` with a pre-set ``query_type``.
    """

    def all(
        self,
        query: str,
        *,
        query_en: str = "",
        query_type: int = 99,
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        base_models: list[str] | None = None,
        model_types: list[Any] | None = None,
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search across all content types.

        Args:
            query: Search query string.
            query_en: English translation of the query for bilingual search.
            query_type: Content type filter (``99`` = all types).
            offset: Pagination offset.
            order_by: Sort order — ``"hot"`` or ``"new"``. ``None`` uses
                the server default.
            page: Page number (1-based).
            page_size: Number of results per page.
            scene: Scene context forwarded to the API.
            url: URL context forwarded to the API.
            base_models: Filter results by base model names.
            model_types: Filter results by model types.
            ss: Additional filter flag forwarded to the API.

        Returns:
            ``APIEnvelope[SearchResult]`` — ``.value.items`` contains the
            results; ``.value.has_more`` indicates more pages; use
            ``.value.offset`` as the ``offset`` for the next page.

        Example:
            >>> result = client.search.all("fantasy portrait")
            >>> for item in result.value.items:
            ...     print(item)
        """
        body = build_search_body(
            query=query,
            query_en=query_en,
            query_type=query_type,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            base_models=base_models,
            model_types=model_types,
            ss=ss,
        )

        env = self._client.request_route(
            Search.SEARCH,
            json=body.model_dump(exclude_none=True),
        )
        return APIEnvelope[SearchResult].model_validate(env)

    def works(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for community works. Shortcut for :meth:`all` with ``query_type=4``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=4,
            offset=offset,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )

    def models(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        base_models: list[str] | None = None,
        model_types: list[Any] | None = None,
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for models. Shortcut for :meth:`all` with ``query_type=2``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=2,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
            base_models=base_models,
            model_types=model_types,
        )

    def characters(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for characters. Shortcut for :meth:`all` with ``query_type=9``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=9,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )

    def ai_apps(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for AI apps. Shortcut for :meth:`all` with ``query_type=14``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=14,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )

    def posts(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for posts. Shortcut for :meth:`all` with ``query_type=4``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=4,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )

    def ai_videos(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for AI videos. Shortcut for :meth:`all` with ``query_type=15``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=15,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )

    def workflows(
        self,
        query: str,
        *,
        query_en: str = "",
        offset: int = 0,
        order_by: Literal["hot", "new"] | None = None,
        page: int = 1,
        page_size: int = 35,
        scene: str = "square",
        url: str = "",
        ss: int | None = None,
    ) -> APIEnvelope[SearchResult]:
        """Search for workflows. Shortcut for :meth:`all` with ``query_type=13``."""
        return self.all(
            query=query,
            query_en=query_en,
            query_type=13,
            offset=offset,
            order_by=order_by,
            page=page,
            page_size=page_size,
            scene=scene,
            url=url,
            ss=ss,
        )
