"""Public /v1 search (space-agnostic)."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from ...models.v1.pagination import Page, Pagination
from ...models.v1.search import CorpusFilter, SearchHit

if TYPE_CHECKING:
    from ..._http import HttpTransport


class SearchResource:
    """client.search — text/image search and similarity search."""

    def __init__(self, http: HttpTransport) -> None:
        self._http = http

    def query(
        self,
        *,
        query_text: str | None = None,
        query_image_url: str | None = None,
        query_image_base64: str | None = None,
        page_size: int = 50,
        cursor: str | None = None,
        representation_profile: str = "general",
        factory_ids: list[str] | None = None,
        worker_ids: list[str] | None = None,
        exclude_factory_ids: list[str] | None = None,
        exclude_worker_ids: list[str] | None = None,
        collection_id: str | None = None,
        created_after: str | None = None,
        created_before: str | None = None,
        corpus: CorpusFilter | dict[str, Any] | None = None,
    ) -> Page[SearchHit]:
        payload: dict[str, Any] = {
            "page_size": page_size,
            "representation_profile": representation_profile,
        }
        if cursor is not None:
            payload["cursor"] = cursor
        if query_text is not None:
            payload["query_text"] = query_text
        if query_image_url is not None:
            payload["query_image_url"] = query_image_url
        if query_image_base64 is not None:
            payload["query_image_base64"] = query_image_base64

        if factory_ids is not None:
            payload["factory_ids"] = factory_ids
        if worker_ids is not None:
            payload["worker_ids"] = worker_ids
        if exclude_factory_ids is not None:
            payload["exclude_factory_ids"] = exclude_factory_ids
        if exclude_worker_ids is not None:
            payload["exclude_worker_ids"] = exclude_worker_ids
        if collection_id is not None:
            payload["collection_id"] = collection_id
        if created_after is not None:
            payload["created_after"] = created_after
        if created_before is not None:
            payload["created_before"] = created_before

        # Default to internal search to avoid requiring datasets scope for typical public users.
        corpus_obj: CorpusFilter | dict[str, Any]
        if corpus is None:
            corpus_obj = CorpusFilter(source="internal")
        else:
            corpus_obj = corpus
        payload["corpus"] = (
            corpus_obj.model_dump(mode="json")
            if isinstance(corpus_obj, CorpusFilter)
            else corpus_obj
        )

        data = self._http.post("/search", json=payload)
        items = [SearchHit.model_validate(i) for i in data.get("data", [])]
        pagination = Pagination.model_validate(data.get("pagination", {}) or {})
        return Page[SearchHit](data=items, pagination=pagination, request_id=data.get("request_id"))

    def iter(
        self,
        *,
        query_text: str | None = None,
        query_image_url: str | None = None,
        query_image_base64: str | None = None,
        page_size: int = 50,
        representation_profile: str = "general",
        factory_ids: list[str] | None = None,
        worker_ids: list[str] | None = None,
        exclude_factory_ids: list[str] | None = None,
        exclude_worker_ids: list[str] | None = None,
        collection_id: str | None = None,
        created_after: str | None = None,
        created_before: str | None = None,
        corpus: CorpusFilter | dict[str, Any] | None = None,
    ):
        from ...models.v1.pagination import auto_paginate

        return auto_paginate(
            self.query,
            query_text=query_text,
            query_image_url=query_image_url,
            query_image_base64=query_image_base64,
            page_size=page_size,
            representation_profile=representation_profile,
            factory_ids=factory_ids,
            worker_ids=worker_ids,
            exclude_factory_ids=exclude_factory_ids,
            exclude_worker_ids=exclude_worker_ids,
            collection_id=collection_id,
            created_after=created_after,
            created_before=created_before,
            corpus=corpus,
        )

    def similar(
        self,
        *,
        reference_clip_id: str | None = None,
        reference_frame_id: str | None = None,
        reference_image_url: str | None = None,
        reference_image_base64: str | None = None,
        page_size: int = 50,
        cursor: str | None = None,
        representation_profile: str = "general",
        exclude_self: bool = True,
        corpus: CorpusFilter | dict[str, Any] | None = None,
    ) -> Page[SearchHit]:
        payload: dict[str, Any] = {
            "page_size": page_size,
            "representation_profile": representation_profile,
            "exclude_self": exclude_self,
        }
        if cursor is not None:
            payload["cursor"] = cursor

        if reference_clip_id is not None:
            payload["reference_clip_id"] = reference_clip_id
        if reference_frame_id is not None:
            payload["reference_frame_id"] = reference_frame_id
        if reference_image_url is not None:
            payload["reference_image_url"] = reference_image_url
        if reference_image_base64 is not None:
            payload["reference_image_base64"] = reference_image_base64

        corpus_obj: CorpusFilter | dict[str, Any]
        if corpus is None:
            corpus_obj = CorpusFilter(source="internal")
        else:
            corpus_obj = corpus
        payload["corpus"] = (
            corpus_obj.model_dump(mode="json")
            if isinstance(corpus_obj, CorpusFilter)
            else corpus_obj
        )

        data = self._http.post("/search/similar", json=payload)
        items = [SearchHit.model_validate(i) for i in data.get("data", [])]
        pagination = Pagination.model_validate(data.get("pagination", {}) or {})
        return Page[SearchHit](data=items, pagination=pagination, request_id=data.get("request_id"))

    def __call__(
        self, query_text: str, *, page_size: int = 50, cursor: str | None = None
    ) -> Page[SearchHit]:
        return self.query(query_text=query_text, page_size=page_size, cursor=cursor)
