"""Keywords resource for Agent Berlin SDK."""

from typing import Literal, Optional

from .._http import HTTPClient
from ..models.search import (
    ClusterKeywordsResponse,
    ClusterListResponse,
    KeywordListResponse,
    KeywordSearchResponse,
)
from ..utils import get_project_domain


class KeywordsResource:
    """Resource for keyword operations.

    Example:
        results = client.keywords.search(query="digital marketing", limit=20)
        for kw in results.keywords:
            print(f"{kw.keyword}: volume={kw.volume}, difficulty={kw.difficulty}")
    """

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

    def list(
        self,
        *,
        limit: Optional[int] = None,
        offset: Optional[int] = None,
    ) -> KeywordListResponse:
        """List all keywords with pagination.

        Returns all keywords in the project with metadata including search volume,
        difficulty, CPC, and intent classification. The project domain is automatically populated.

        Args:
            limit: Maximum number of keywords to return (default: 100, max: 1000).
            offset: Number of keywords to skip for pagination (default: 0).

        Returns:
            KeywordListResponse with keywords list and total count.

        Example:
            # Get first 100 keywords
            result = client.keywords.list()
            for kw in result.keywords:
                print(f"{kw.keyword}: volume={kw.volume}")

            # Paginate through all keywords
            result = client.keywords.list(limit=100, offset=100)
        """
        payload: dict[str, object] = {
            "project_domain": get_project_domain(),
        }
        if limit is not None:
            payload["limit"] = limit
        if offset is not None:
            payload["offset"] = offset

        data = self._http.post("/keywords/list", json=payload)
        return KeywordListResponse.model_validate(data)

    def search(
        self,
        query: str,
        *,
        limit: Optional[int] = None,
        match_type: Optional[Literal["semantic", "exact", "contains"]] = None,
    ) -> KeywordSearchResponse:
        """Search for keywords.

        Returns relevant keywords with metadata including search volume,
        difficulty, CPC, and intent classification. The project domain is automatically populated.

        Args:
            query: Search query string.
            limit: Maximum results (default: 10, max: 50).
            match_type: Search mode (default: "semantic"):
                - "semantic": Hybrid AI search using embeddings and BM25 (default)
                - "exact": Case-insensitive exact string match
                - "contains": Case-insensitive substring/contains match

        Returns:
            KeywordSearchResponse with matching keywords and metadata.

        Example:
            # Semantic search (default)
            results = client.keywords.search(query="running shoes")

            # Exact match
            results = client.keywords.search(query="running shoes", match_type="exact")

            # Substring match
            results = client.keywords.search(query="running", match_type="contains")
        """
        payload: dict[str, object] = {
            "project_domain": get_project_domain(),
            "query": query,
        }
        if limit is not None:
            payload["limit"] = limit
        if match_type is not None:
            payload["match_type"] = match_type

        data = self._http.post("/keywords/search", json=payload)
        return KeywordSearchResponse.model_validate(data)

    def list_clusters(
        self,
        *,
        representative_count: Optional[int] = None,
    ) -> ClusterListResponse:
        """List all keyword clusters with representative keywords.

        Returns a summary of all HDBSCAN clusters including their sizes and
        representative keywords (highest volume keywords in each cluster).
        The project domain is automatically populated.

        Args:
            representative_count: Number of representative keywords per cluster
                (default: 3, max: 10).

        Returns:
            ClusterListResponse with list of clusters and metadata.

        Example:
            clusters = client.keywords.list_clusters()
            for cluster in clusters.clusters:
                print(f"Cluster {cluster.cluster_id}: {cluster.size} keywords")
                print(f"  Representatives: {', '.join(cluster.representative_keywords)}")
        """
        payload: dict[str, object] = {
            "project_domain": get_project_domain(),
        }
        if representative_count is not None:
            payload["representative_count"] = representative_count

        data = self._http.post("/keywords/clusters", json=payload)
        return ClusterListResponse.model_validate(data)

    def get_cluster_keywords(
        self,
        cluster_id: int,
        *,
        limit: Optional[int] = None,
        offset: Optional[int] = None,
    ) -> ClusterKeywordsResponse:
        """Get keywords belonging to a specific cluster.

        Returns keywords from a specific cluster with pagination support.
        Use cluster_id=-1 to get noise keywords (unclustered).
        The project domain is automatically populated.

        Args:
            cluster_id: The cluster ID to fetch keywords for (-1 for noise).
            limit: Maximum keywords to return (default: 50, max: 1000).
            offset: Number of keywords to skip for pagination (default: 0).

        Returns:
            ClusterKeywordsResponse with list of keywords and pagination info.

        Example:
            # Get keywords from cluster 0
            result = client.keywords.get_cluster_keywords(0, limit=20)
            for kw in result.keywords:
                print(f"{kw.keyword}: volume={kw.volume}")

            # Get noise keywords (unclustered)
            noise = client.keywords.get_cluster_keywords(-1)
        """
        payload: dict[str, object] = {
            "project_domain": get_project_domain(),
            "cluster_id": cluster_id,
        }
        if limit is not None:
            payload["limit"] = limit
        if offset is not None:
            payload["offset"] = offset

        data = self._http.post("/keywords/clusters/keywords", json=payload)
        return ClusterKeywordsResponse.model_validate(data)
