from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


class ExplainHints(BaseModel):
    model_config = ConfigDict(extra="forbid")

    paths: list[str] = Field(default_factory=list)
    symbols: list[str] = Field(default_factory=list)
    endpoints: list[str] = Field(default_factory=list)
    commands: list[str] = Field(default_factory=list)


class ExplainIntent(BaseModel):
    model_config = ConfigDict(extra="forbid")

    raw_query: str
    normalized_query: str
    keywords: list[str] = Field(default_factory=list)
    hints: ExplainHints = Field(default_factory=ExplainHints)
    include_tests: bool = False
    expected_entry_types: list[Literal["http", "cli"]] = Field(default_factory=list)
    depth: Literal["high", "medium", "deep"] = "medium"


class CodeLocation(BaseModel):
    model_config = ConfigDict(extra="forbid")

    path: str
    start_line: int | None = None
    end_line: int | None = None


class LayeredRetrievalItem(BaseModel):
    model_config = ConfigDict(extra="forbid")

    source: str
    content: str
    layer: str
    title: str
    metadata: dict[str, Any] = Field(default_factory=dict)
    score: float | None = None
    location: CodeLocation | None = None


class TracePath(BaseModel):
    model_config = ConfigDict(extra="forbid")

    symbol_ids: list[str] = Field(default_factory=list)
    score: float = 0.0
    entrypoint_id: str | None = None
    notes: list[str] = Field(default_factory=list)


class EvidenceItem(BaseModel):
    model_config = ConfigDict(extra="forbid")

    evidence_id: str
    kind: Literal["entrypoint", "symbol", "edge", "excerpt"]
    summary: str
    location: CodeLocation | None = None
    supports: list[str] = Field(default_factory=list)


class CodeExcerpt(BaseModel):
    model_config = ConfigDict(extra="forbid")

    evidence_id: str
    symbol_id: str | None = None
    title: str
    path: str
    start_line: int | None = None
    end_line: int | None = None
    content: str
    focus: str = "overview"


class ExplainPack(BaseModel):
    model_config = ConfigDict(extra="forbid")

    intent: ExplainIntent
    selected_entrypoints: list[LayeredRetrievalItem] = Field(default_factory=list)
    seed_symbols: list[LayeredRetrievalItem] = Field(default_factory=list)
    trace_paths: list[TracePath] = Field(default_factory=list)
    evidence_index: dict[str, EvidenceItem] = Field(default_factory=dict)
    code_excerpts: list[CodeExcerpt] = Field(default_factory=list)
    missing: list[str] = Field(default_factory=list)
    conflicts: list[str] = Field(default_factory=list)
