"""Search domain models."""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field


class SearchDocument(BaseModel):
    """A document to be indexed for search.

    Attributes:
        id: Unique document identifier within the index.
        content: Arbitrary key-value fields that make up the document body.
        index_name: Name of the index this document belongs to.
    """

    id: str
    content: dict[str, Any]
    index_name: str


class SearchQuery(BaseModel):
    """Parameters for executing a search query.

    Attributes:
        query: The search string.
        filters: Key-value filters to narrow results (e.g. ``{"status": "active"}``).
        facets: Field names to compute facet counts for.
        page: Page number (1-based).
        per_page: Number of results per page.
        sort_by: Field name to sort results by (prefix with ``-`` for descending).
        highlight: Whether to include highlight snippets in results.
    """

    query: str
    filters: dict[str, Any] = Field(default_factory=dict)
    facets: list[str] = Field(default_factory=list)
    page: int = Field(default=1, ge=1)
    per_page: int = Field(default=20, ge=1, le=200)
    sort_by: str | None = None
    highlight: bool = True


class SearchResult(BaseModel):
    """A single search hit.

    Attributes:
        id: Document identifier.
        score: Relevance score (higher is better).
        highlights: Field name to highlighted snippet mapping.
        document: The full document content.
    """

    id: str
    score: float = 0.0
    highlights: dict[str, str] = Field(default_factory=dict)
    document: dict[str, Any] = Field(default_factory=dict)


class SearchResponse(BaseModel):
    """Paginated search response.

    Attributes:
        results: Matching documents for the current page.
        total: Total number of matching documents across all pages.
        facets: Facet name to value-count mapping.
        query_time_ms: Time spent executing the query in milliseconds.
        page: Current page number.
        per_page: Number of results per page.
    """

    results: list[SearchResult] = Field(default_factory=list)
    total: int = 0
    facets: dict[str, dict[str, int]] = Field(default_factory=dict)
    query_time_ms: float = 0.0
    page: int = 1
    per_page: int = 20


class IndexConfig(BaseModel):
    """Configuration for a search index.

    Attributes:
        name: Index identifier.
        searchable_fields: Fields included in full-text search.
        filterable_fields: Fields available for filtering.
        sortable_fields: Fields available for sorting.
        ranking_rules: Ordered list of ranking rules (backend-specific).
    """

    name: str
    searchable_fields: list[str] = Field(default_factory=list)
    filterable_fields: list[str] = Field(default_factory=list)
    sortable_fields: list[str] = Field(default_factory=list)
    ranking_rules: list[str] = Field(default_factory=list)
