"""Search API data models"""

from typing import Optional, List, Dict, Any
from pydantic import Field, field_validator
from .base import OctenBaseModel
from ..utils.constants import (
    SEARCH_TYPES,
    TIME_BASIS_OPTIONS,
    FORMAT_OPTIONS,
    SAFESEARCH_OPTIONS,
)


class HighlightOptions(OctenBaseModel):
    """Highlight options configuration

    Attributes:
        enable: Whether to return highlighted content
        max_tokens: Maximum token count for highlighted content
    """

    enable: bool = Field(True, description="Whether to return highlights")
    max_tokens: int = Field(
        300,
        ge=100,
        le=2048,
        description="Max tokens for highlight",
    )


class FullContentOptions(OctenBaseModel):
    """Full content options configuration

    Attributes:
        enable: Whether to return full content
        max_tokens: Maximum token count for full content
    """

    enable: bool = Field(False, description="Whether to return full content")
    max_tokens: int = Field(
        1000,
        ge=1,
        le=100000,
        description="Max tokens for content",
    )


class SearchRequest(OctenBaseModel):
    """Search API request model

    Attributes:
        query: Search queryString
        search_type: Search type（auto/keyword/semantic）
        count: Number of results
        include_domains: List of included domains
        exclude_domains: List of excluded domains
        include_text: List of text that must be included
        exclude_text: List of text that must be excluded
        time_basis: Time basis (auto/published/crawled)
        start_time: Start time (ISO 8601 format)
        end_time: End time (ISO 8601 format)
        highlight: Highlight options
        format: Content format (text/markdown)
        safesearch: Safesearch level (off/strict)
        full_content: Full content options
    """

    query: str = Field(
        ...,
        max_length=500,
        description="Search query",
    )
    search_type: Optional[str] = Field(
        "auto",
        description="Search type: auto/keyword/semantic",
    )
    count: Optional[int] = Field(
        5,
        ge=1,
        le=100,
        description="Number of results",
    )
    include_domains: Optional[List[str]] = Field(
        None,
        description="Include domains",
    )
    exclude_domains: Optional[List[str]] = Field(
        None,
        description="Exclude domains",
    )
    include_text: Optional[List[str]] = Field(
        None,
        description="Text that must be included",
    )
    exclude_text: Optional[List[str]] = Field(
        None,
        description="Text that must be excluded",
    )
    time_basis: Optional[str] = Field(
        "auto",
        description="Time basis: auto/published/crawled",
    )
    start_time: Optional[str] = Field(
        None,
        description="Start time ISO 8601",
    )
    end_time: Optional[str] = Field(
        None,
        description="End time ISO 8601",
    )
    highlight: Optional[HighlightOptions] = Field(
        None,
        description="Highlight options",
    )
    format: Optional[str] = Field(
        "text",
        description="Format: text/markdown",
    )
    safesearch: Optional[str] = Field(
        "strict",
        description="Safesearch: off/strict",
    )
    full_content: Optional[FullContentOptions] = Field(
        None,
        description="Full content options",
    )

    @field_validator("search_type")
    @classmethod
    def validate_search_type(cls, v: Optional[str]) -> Optional[str]:
        """validateSearch type"""
        if v is not None and v not in SEARCH_TYPES:
            raise ValueError(f"search_type must be one of {SEARCH_TYPES}")
        return v

    @field_validator("time_basis")
    @classmethod
    def validate_time_basis(cls, v: Optional[str]) -> Optional[str]:
        """Validate time basis"""
        if v is not None and v not in TIME_BASIS_OPTIONS:
            raise ValueError(f"time_basis must be one of {TIME_BASIS_OPTIONS}")
        return v

    @field_validator("format")
    @classmethod
    def validate_format(cls, v: Optional[str]) -> Optional[str]:
        """Validate format"""
        if v is not None and v not in FORMAT_OPTIONS:
            raise ValueError(f"format must be one of {FORMAT_OPTIONS}")
        return v

    @field_validator("safesearch")
    @classmethod
    def validate_safesearch(cls, v: Optional[str]) -> Optional[str]:
        """Validate safesearch"""
        if v is not None and v not in SAFESEARCH_OPTIONS:
            raise ValueError(f"safesearch must be one of {SAFESEARCH_OPTIONS}")
        return v


class SearchResult(OctenBaseModel):
    """Search result item

    Attributes:
        title: Page title
        url: Page URL
        highlight: Highlighted summary
        full_content: Full content
        authors: Author information
        time_published: Published time
        time_last_crawled: Last crawled time
    """

    title: str = Field(..., description="Title")
    url: str = Field(..., description="URL")
    highlight: Optional[str] = Field(None, description="Highlighted summary")
    full_content: Optional[str] = Field(None, description="Full content")
    authors: Optional[str] = Field(None, description="Authors")
    time_published: Optional[str] = Field(None, description="Published time")
    time_last_crawled: Optional[str] = Field(None, description="Last crawled time")


class SearchResponse(OctenBaseModel):
    """Search API response model

    Attributes:
        code: Response code (0 for success)
        msg: Response message
        data: Response data
        meta: Metadata (includes usage, latency, etc.)
    """

    code: int = Field(..., description="Response code")
    msg: str = Field(..., description="Response message")
    data: Dict[str, Any] = Field(..., description="Response data")
    meta: Dict[str, Any] = Field(..., description="Metadata")

    @property
    def results(self) -> List[Dict[str, Any]]:
        """GetList of search results"""
        return self.data.get("results", [])

    @property
    def query(self) -> Optional[str]:
        """GetQueryString"""
        return self.data.get("query")

    @property
    def search_type(self) -> Optional[str]:
        """Get actually used search type"""
        return self.data.get("search_type")

    @property
    def usage(self) -> Optional[Dict[str, Any]]:
        """GetUsage information"""
        return self.meta.get("usage")

    @property
    def latency(self) -> Optional[Dict[str, Any]]:
        """Get latency information"""
        return self.meta.get("latency")

    @property
    def warning(self) -> Optional[str]:
        """Get warning messages"""
        return self.meta.get("warning")
