"""
Calls Perplexity's /search endpoint to search the web.
"""

from typing import Dict, List, Optional, TypedDict, Union

import httpx

from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.llms.base_llm.search.transformation import (
    BaseSearchConfig,
    SearchResponse,
    SearchResult,
)
from litellm.secret_managers.main import get_secret_str


class _PerplexitySearchRequestRequired(TypedDict):
    """Required fields for Perplexity Search API request."""

    query: Union[str, List[str]]  # Required - search query or queries


class PerplexitySearchRequest(_PerplexitySearchRequestRequired, total=False):
    """
    Perplexity Search API request format.
    Based on: https://docs.perplexity.ai/api-reference/search-post
    """

    max_results: int  # Optional - maximum number of results (1-20), default 10
    search_domain_filter: List[str]  # Optional - list of domains to filter (max 20)
    max_tokens_per_page: int  # Optional - max tokens per page, default 1024
    country: str  # Optional - country code filter (e.g., 'US', 'GB', 'DE')


class PerplexitySearchConfig(BaseSearchConfig):
    PERPLEXITY_API_BASE = "https://api.perplexity.ai"

    @staticmethod
    def ui_friendly_name() -> str:
        return "Perplexity"

    def validate_environment(
        self,
        headers: Dict,
        api_key: Optional[str] = None,
        api_base: Optional[str] = None,
        **kwargs,
    ) -> Dict:
        """
        Validate environment and return headers.
        """
        api_key = api_key or get_secret_str("PERPLEXITYAI_API_KEY")
        if not api_key:
            raise ValueError(
                "PERPLEXITYAI_API_KEY is not set. Set `PERPLEXITYAI_API_KEY` environment variable."
            )
        headers["Authorization"] = f"Bearer {api_key}"
        headers["Content-Type"] = "application/json"
        return headers

    def get_complete_url(
        self,
        api_base: Optional[str],
        optional_params: dict,
        data: Optional[Union[Dict, List[Dict]]] = None,
        **kwargs,
    ) -> str:
        """
        Get complete URL for Search endpoint.
        """
        api_base = (
            api_base
            or get_secret_str("PERPLEXITY_API_BASE")
            or self.PERPLEXITY_API_BASE
        )

        # append "/search" to the api base if it's not already there
        if not api_base.endswith("/search"):
            api_base = f"{api_base}/search"

        return api_base

    def transform_search_request(
        self,
        query: Union[str, List[str]],
        optional_params: dict,
        **kwargs,
    ) -> Dict:
        """
        Transform Search request to Perplexity API format.

        Note: LiteLLM's native spec is the perplexity search spec.

        There's no transformation needed for the request data.

        https://docs.perplexity.ai/api-reference/search-post

        Args:
            query: Search query (string or list of strings)
            optional_params: Optional parameters for the request
                - max_results: Maximum number of search results (1-20)
                - search_domain_filter: List of domains to filter (max 20)
                - max_tokens_per_page: Max tokens per page (default 1024)
                - country: Country code filter (e.g., 'US', 'GB', 'DE')

        Returns:
            Dict with typed request data following PerplexitySearchRequest spec
        """
        request_data: PerplexitySearchRequest = {
            "query": query,
        }

        # Add optional parameters following Perplexity API spec (only if not None)
        max_results = optional_params.get("max_results")
        if max_results is not None:
            request_data["max_results"] = max_results

        search_domain_filter = optional_params.get("search_domain_filter")
        if search_domain_filter is not None:
            request_data["search_domain_filter"] = search_domain_filter

        max_tokens_per_page = optional_params.get("max_tokens_per_page")
        if max_tokens_per_page is not None:
            request_data["max_tokens_per_page"] = max_tokens_per_page

        country = optional_params.get("country")
        if country is not None:
            request_data["country"] = country

        return dict(request_data)

    def transform_search_response(
        self,
        raw_response: httpx.Response,
        logging_obj: LiteLLMLoggingObj,
        **kwargs,
    ) -> SearchResponse:
        """
        Transform Perplexity API response to standard SearchResponse format.

        Args:
            raw_response: Raw httpx response from Perplexity API
            logging_obj: Logging object for tracking

        Returns:
            SearchResponse with standardized format
        """
        response_json = raw_response.json()

        # Transform results to SearchResult objects
        results = []
        for result in response_json.get("results", []):
            search_result = SearchResult(
                title=result.get("title", ""),
                url=result.get("url", ""),
                snippet=result.get("snippet", ""),
                date=result.get("date"),
                last_updated=result.get("last_updated"),
            )
            results.append(search_result)

        return SearchResponse(
            results=results,
            object="search",
        )
