from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


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

    path: str = ""
    method: str = ""
    request_schema: dict[str, Any] | None = None
    response_schema: dict[str, Any] | None = None
    raw_yaml: str = ""
    diagnostics: dict[str, Any] = Field(default_factory=dict)


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

    intent: str
    sub_intent: str
    layers_used: list[str] = Field(default_factory=list)
    documents_found: int = 0
    facts_found: int = 0
    relations_found: int = 0
    openapi_fields_extracted: int = 0
    missing_required_fields: list[str] = Field(default_factory=list)
    openapi_status: dict[str, bool] = Field(default_factory=dict)
    prompt_used: str = ""
    llm_mode: str = "prose"
    output_valid: bool = True
    matched_intent_source: str = "deterministic"
    matched_anchor_type: str = "none"
    matched_anchor_value: str | None = None
    exact_anchor_match: bool = False
    docs_layers_requested: list[str] = Field(default_factory=list)
    docs_layers_with_hits: list[str] = Field(default_factory=list)
    planned_layers: list[str] = Field(default_factory=list)
    executed_layers: list[str] = Field(default_factory=list)
    non_empty_layers: list[str] = Field(default_factory=list)
    layer_diagnostics: dict[str, Any] = Field(default_factory=dict)
    query_entity_candidates: list[str] = Field(default_factory=list)
    resolved_entity_candidates: list[str] = Field(default_factory=list)
    query_anchor_candidates: list[str] = Field(default_factory=list)
    resolved_anchor_candidates: list[str] = Field(default_factory=list)
    anchor_candidates: list[str] = Field(default_factory=list)
    selected_anchor: str | None = None
    anchor_selection_reason: str = ""
    anchor_match_type: str = ""
    doc_ids: list[str] = Field(default_factory=list)
    doc_paths: list[str] = Field(default_factory=list)
    doc_titles: list[str] = Field(default_factory=list)
    relation_hits_count: int = 0
    relation_targets: list[str] = Field(default_factory=list)
    selected_doc_ids: list[str] = Field(default_factory=list)
    selected_fact_ids: list[str] = Field(default_factory=list)
    selected_relation_ids: list[str] = Field(default_factory=list)
    selected_chunk_ids: list[str] = Field(default_factory=list)
    selected_entity_ids: list[str] = Field(default_factory=list)
    selected_workflow_ids: list[str] = Field(default_factory=list)
    fallback_doc_hits_count: int = 0
    fallback_used: bool = False
    fact_hits: int = 0
    entity_hits: int = 0
    evidence_summary: dict[str, Any] = Field(default_factory=dict)
    gate_decision: str = "ready"
    gate_decision_reason: str = ""
    gate_missing_requirements: list[str] = Field(default_factory=list)
    gate_satisfied_requirements: list[str] = Field(default_factory=list)
    openapi_evidence: dict[str, bool] = Field(default_factory=dict)
    requested_fragment_type: str | None = None
    fragment_evidence_found: list[str] = Field(default_factory=list)
    fragment_missing_requirements: list[str] = Field(default_factory=list)
    prompt: dict[str, Any] = Field(default_factory=dict)
    answer_mode: str = "answered"
    degrade_reason: str | None = None
    degraded_reason: str | None = None
    code_intents_stubbed: bool = False


@dataclass(slots=True)
class DocsEvidenceBundle:
    intent: str
    sub_intent: str
    documents: list[dict[str, Any]] = field(default_factory=list)
    facts: list[dict[str, Any]] = field(default_factory=list)
    entities: list[dict[str, Any]] = field(default_factory=list)
    workflows: list[dict[str, Any]] = field(default_factory=list)
    relations: list[dict[str, Any]] = field(default_factory=list)
    chunks: list[dict[str, Any]] = field(default_factory=list)
    raw_rows: list[dict[str, Any]] = field(default_factory=list)


@dataclass(slots=True)
class DocsQAPipelineResult:
    user_query: str
    rag_session_id: str
    router_result: Any
    retrieval_request: Any
    evidence_bundle: DocsEvidenceBundle
    answer: str
    diagnostics: DocsDiagnostics
    openapi_result: OpenAPIResult | None = None
    prompt_name: str = ""
    llm_request: dict[str, Any] = field(default_factory=dict)
    output_valid: bool = True
    answer_mode: str = "answered"
    degraded_reason: str = ""
    raw_rows: list[dict[str, Any]] = field(default_factory=list)
    timings_ms: dict[str, int] = field(default_factory=dict)
    mode: str = "full"
