"""Pydantic models for search API responses (pages, keywords)."""

from typing import List, Optional

from pydantic import BaseModel, Field


# Evidence model for page search results
class Evidence(BaseModel):
    """Evidence chunk with h_path and text."""

    h_path: Optional[str] = None
    text: str


# Topic info model
class TopicInfo(BaseModel):
    """Topic classification for a page."""

    topics: List[str] = Field(default_factory=list)
    topic_scores: List[float] = Field(default_factory=list)
    page_type: Optional[str] = None  # "pillar" or "landing"
    assigned_topic: Optional[str] = None


# Advanced page search models


class SimilarPage(BaseModel):
    """Single similar page in advanced search results."""

    target_page_url: str
    similarity_score: float
    match_type: str  # "page_to_page" or "chunk_to_page"
    chunk_text: Optional[str] = None
    page_type: Optional[str] = None  # "pillar", "landing", or None
    assigned_topic: Optional[str] = None
    # Rich fields from full search pipeline
    title: Optional[str] = None
    h1: Optional[str] = None
    meta_description: Optional[str] = None
    evidence: Optional[List[Evidence]] = None  # Top chunks with h_path + text
    domain: Optional[str] = None
    status_code: Optional[str] = None
    topic_info: Optional[TopicInfo] = None  # Full topic info


class SimilarChunkSet(BaseModel):
    """Similar pages for a specific chunk (used with get(detailed=True))."""

    chunk_id: int
    chunk_text: str
    similar_pages: List[SimilarPage] = Field(default_factory=list)


class PageSearchResponse(BaseModel):
    """Response for page search."""

    source_page_url: Optional[str] = None
    source_page_type: Optional[str] = None  # "pillar", "landing", or None
    source_assigned_topic: Optional[str] = None
    similar_pages: List[SimilarPage] = Field(default_factory=list)
    similar_chunks: List[SimilarChunkSet] = Field(default_factory=list)


# Keyword search models


class LocationMetrics(BaseModel):
    """Metrics for a keyword in a specific geographic location."""

    code: str  # Location code (e.g., "us", "uk", "de")
    volume: Optional[int] = None  # Search volume
    position: Optional[int] = None  # SERP position for user's brand domain
    cpc: Optional[float] = None  # Cost per click
    difficulty: Optional[int] = None  # Keyword Difficulty (0-100)


class KeywordResult(BaseModel):
    """Single keyword with metadata."""

    keyword: str
    intent: Optional[str] = None  # informational, commercial, transactional, navigational
    locations: List[LocationMetrics] = Field(default_factory=list)  # Location-specific metrics


class KeywordSearchResponse(BaseModel):
    """Response for keyword search."""

    keywords: List[KeywordResult] = Field(default_factory=list)
    total: int


class KeywordListResponse(BaseModel):
    """Response for listing all keywords with pagination."""

    keywords: List[KeywordResult] = Field(default_factory=list)
    total: int


# Cluster listing models


class ClusterSummary(BaseModel):
    """Single cluster summary."""

    cluster_id: int
    size: int
    representative_keywords: List[str] = Field(default_factory=list)


class ClusterListResponse(BaseModel):
    """Response for listing all clusters."""

    clusters: List[ClusterSummary] = Field(default_factory=list)
    noise_count: int
    total_keywords: int
    cluster_count: int


class ClusterKeywordResult(BaseModel):
    """Single keyword in a cluster."""

    keyword: str
    cluster_id: Optional[int] = None
    intent: Optional[str] = None
    locations: List[LocationMetrics] = Field(default_factory=list)  # Location-specific metrics


class ClusterKeywordsResponse(BaseModel):
    """Response for getting keywords in a cluster."""

    keywords: List[ClusterKeywordResult] = Field(default_factory=list)
    total: int
    cluster_id: int
    limit: int
    offset: int


# Get page models


class PageLink(BaseModel):
    """Link in page details."""

    source_url: str
    target_url: str
    anchor_text: Optional[str] = None
    domain_type: str  # "internal" or "external"
    source_title: Optional[str] = None
    target_title: Optional[str] = None


class PageLinksDetail(BaseModel):
    """Links for a page."""

    inlinks: List[PageLink] = Field(default_factory=list)
    outlinks: List[PageLink] = Field(default_factory=list)


class PageTopicInfo(BaseModel):
    """Topic classification for a page."""

    topics: List[str] = Field(default_factory=list)
    topic_scores: List[float] = Field(default_factory=list)
    page_type: Optional[str] = None  # "pillar" or "landing"
    assigned_topic: Optional[str] = None


class PageDetailResponse(BaseModel):
    """Detailed page information."""

    url: str
    title: Optional[str] = None
    meta_description: Optional[str] = None
    h1: Optional[str] = None
    domain: Optional[str] = None
    links: Optional[PageLinksDetail] = None
    topic_info: Optional[PageTopicInfo] = None
    content: Optional[str] = None
    content_length: int = 0
    # Only populated when detailed=True
    similar_pages: Optional[List[SimilarPage]] = None
    similar_chunks: Optional[List[SimilarChunkSet]] = None


# Page list models


class PageListItem(BaseModel):
    """Single page in list response."""

    url: str
    title: str
    meta_description: Optional[str] = None
    h1: Optional[str] = None
    domain: Optional[str] = None


class PageListResponse(BaseModel):
    """Response for listing pages."""

    pages: List[PageListItem] = Field(default_factory=list)
    total: int
    limit: int
    offset: int


