"""Pydantic models for the research (深度研究) API.

深度研究接口的请求/响应数据模型。
定义研究任务描述、研究计划、SSE 流式数据块、
以及 plan/run/rerun 各阶段的请求和响应结构。
"""

from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, Field

from app.api.schemas.search import MatchedChunk


class ResearchRequest(BaseModel):
    """Payload for ``POST /research``."""

    question: str = Field(..., min_length=1, max_length=2000, description="研究问题")
    session_id: str | None = Field(None, description="可选的会话 ID，用于多轮对话")
    seed_doc_ids: list[str] | None = Field(None, description="显式导入的文档 ID 列表")


class ResearchTask(BaseModel):
    """Structured task definition for Deep Research.

    深度研究任务定义，包含研究模式、主题、范围限定、输出模板等参数。
    """

    mode: Literal["quick", "deep"] = Field("deep", description="研究模式")
    topic: str = Field(..., min_length=1, max_length=500, description="研究主题")
    question: str = Field(..., min_length=1, max_length=2000, description="核心研究问题")
    goal: str | None = Field(None, max_length=2000, description="研究目标")
    time_range: str | None = Field(None, max_length=200, description="时间范围")
    region_scope: str | None = Field(None, max_length=200, description="地域范围")
    org_scope: str | None = Field(None, max_length=200, description="部门范围")
    output_template: Literal[
        "comprehensive",
        "policy_brief",
        "timeline",
        "comparison",
        "implementation",
        "briefing_outline",
        "speech_draft",
    ] = Field("comprehensive", description="输出模板")
    depth_level: Literal["standard", "deep", "comprehensive"] = Field(
        "deep",
        description="研究深度",
    )
    required_doc_ids: list[str] = Field(default_factory=list, description="必须纳入的文档")
    required_matter_ids: list[str] = Field(default_factory=list, description="必须关注的事项")
    enable_kb_search: bool = Field(True, description="是否开启知识库查询（关闭则仅用资料篮文档）")


class ResearchPlan(BaseModel):
    """Plan produced before the research run starts.

    研究计划：由 LLM 生成，包含目标拆解、子问题、检索重点和章节大纲，
    用户确认后作为 run 阶段的执行蓝图。
    """

    summary: str = Field(..., description="研究计划摘要")
    objectives: list[str] = Field(default_factory=list, description="目标拆解")
    sub_questions: list[str] = Field(default_factory=list, description="子问题")
    retrieval_focus: list[str] = Field(default_factory=list, description="检索重点")
    section_outline: list[str] = Field(default_factory=list, description="预计章节结构")
    expected_deliverables: list[str] = Field(default_factory=list, description="预期交付")
    notes: list[str] = Field(default_factory=list, description="风险与提示")
    included_doc_ids: list[str] = Field(default_factory=list, description="明确纳入的文档")
    included_matter_ids: list[str] = Field(default_factory=list, description="明确纳入的事项")


class ResearchPlanRequest(BaseModel):
    """Payload for generating a research plan."""

    session_id: str | None = Field(None, description="可选的会话 ID")
    task: ResearchTask
    seed_doc_ids: list[str] | None = Field(None, description="显式导入的文档 ID 列表")


class ResearchPlanResponse(BaseModel):
    """Response body for a generated research plan."""

    session_id: str | None = None
    task: ResearchTask
    plan: ResearchPlan


class ResearchRunRequest(BaseModel):
    """Payload for executing a confirmed research plan."""

    session_id: str | None = Field(None, description="可选的会话 ID")
    task: ResearchTask
    plan: ResearchPlan
    seed_doc_ids: list[str] | None = Field(None, description="显式导入的文档 ID 列表")


class ResearchSectionRerunRequest(BaseModel):
    """Payload for re-running a specific report section."""

    session_id: str | None = Field(None, description="可选的会话 ID")
    task: ResearchTask
    plan: ResearchPlan
    section_title: str = Field(..., min_length=1, max_length=200, description="要重跑的章节标题")
    section_summary: str | None = Field(None, max_length=2000, description="当前章节摘要")
    source_doc_ids: list[str] | None = Field(None, description="当前章节已绑定的文档 ID")
    seed_doc_ids: list[str] | None = Field(None, description="显式导入的文档 ID 列表")


class ResearchChunk(BaseModel):
    """A single SSE chunk sent during streaming research output.

    ``type`` indicates the kind of content:
    - ``thinking`` – intermediate reasoning steps
    - ``text`` – final answer text
    - ``reference`` – a cited document reference
    - ``done`` – signals end of stream
    - ``error`` – an error occurred
    """

    type: str = Field(
        ...,
        description=(
            "thinking | text | reference | progress | plan | summary | finding | "
            "conflict | section | open_question | source_group | follow_up | done | error"
        ),
    )
    content: str | None = None
    stage: str | None = None
    status: str | None = None
    title: str | None = None
    severity: str | None = None
    strength: str | None = None
    doc_id: str | None = None
    doc_number: str | None = None
    chunk_index: int | None = None
    relevance_score: float | None = None
    payload: dict[str, Any] | None = None


class ResearchReference(BaseModel):
    """A document reference cited by the research answer."""

    doc_id: str
    title: str
    doc_number: str | None = None
    relevance_score: float | None = None
    matched_chunks: list[MatchedChunk] = Field(default_factory=list)


# ---------------------------------------------------------------------------
# Research Records API models
# ---------------------------------------------------------------------------

_OUTPUT_TEMPLATE_LITERAL = Literal[
    "comprehensive", "policy_brief", "timeline",
    "comparison", "implementation", "briefing_outline", "speech_draft",
]


class ResearchRecordCreateRequest(BaseModel):
    """Payload for ``POST /research/records``."""

    title: str = Field(..., min_length=1, max_length=500, description="研究标题")
    mode: Literal["quick", "deep"] = Field("deep", description="研究模式")
    output_template: _OUTPUT_TEMPLATE_LITERAL = Field("comprehensive", description="输出模板")
    task: ResearchTask = Field(..., description="研究任务定义（必填）")
    imported_items: list[dict[str, Any]] | None = Field(None, description="导入的素材列表")
    seed_doc_ids: list[str] | None = Field(None, description="显式导入的文档 ID 列表")


class ResearchRecordSummary(BaseModel):
    """List-level summary of a research record."""

    id: str
    title: str
    mode: str
    status: str
    output_template: str
    summary: str | None = None
    archived: bool = False
    version_no: int = 1
    created_at: str
    updated_at: str


class ResearchRecordListResponse(BaseModel):
    """Response for ``GET /research/records``."""

    records: list[ResearchRecordSummary]
    total: int


class ResearchRecordDetail(BaseModel):
    """Full record detail (without report body)."""

    id: str
    title: str
    mode: str
    status: str
    output_template: str
    summary: str | None = None
    archived: bool = False
    session_id: str | None = None
    task: dict[str, Any] | None = None
    plan: dict[str, Any] | None = None
    references: list[dict[str, Any]] | None = None
    imported_items: list[dict[str, Any]] | None = None
    clarification_messages: list[dict[str, Any]] | None = None
    chat_messages: list[dict[str, Any]] | None = None
    notes: str | None = None
    parent_record_id: str | None = None
    root_record_id: str | None = None
    version_no: int = 1
    last_error: str | None = None
    created_at: str
    updated_at: str
    completed_at: str | None = None
    # Latest run metadata for detail-page recovery (C7)
    latest_run_id: str | None = None
    latest_run_status: str | None = None
    latest_run_type: str | None = None
    latest_run_started_at: str | None = None


class ResearchRecordReportResponse(BaseModel):
    """Response for ``GET /research/records/{id}/report``."""

    record_id: str
    report: dict[str, Any] | None = None
    final_document_md: str | None = None
    updated_at: str | None = None


class ResearchRecordPlanRequest(BaseModel):
    """Payload for ``POST /research/records/{id}/plan``.

    Phase 1: front-end sends empty ``{}``. The backend reads task from
    ``record.task_json``.
    """
    pass


class ResearchRecordSectionRerunRequest(BaseModel):
    """Payload for ``POST /research/records/{id}/sections/rerun``."""

    section_title: str = Field(..., min_length=1, max_length=200, description="要重跑的章节标题")
    section_summary: str | None = Field(None, max_length=2000, description="当前章节摘要")
    source_doc_ids: list[str] | None = Field(None, description="当前章节已绑定的文档 ID")


class ResearchRecordRunResponse(BaseModel):
    """Response for ``POST /research/records/{id}/run``."""

    run_id: str
    record_id: str
    status: str
