from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, model_validator


class RemediationRequiredInputItem(BaseModel):
    """Một input bắt buộc cần có trước khi lập hoặc thực thi phương án khắc phục."""

    input_code: str
    label: str
    status: str = "missing"
    description: str | None = None
    example_value: str | None = None
    source_hint: str | None = None
    required: bool = True
    blocking: bool = False
    metadata: dict[str, Any] = Field(default_factory=dict)


class RemediationArtifactRequirementItem(BaseModel):
    """Một đầu ra hoặc artifact cần được tạo/chốt để đóng finding."""

    artifact_code: str
    label: str
    artifact_type: str
    required: bool = True
    review_required: bool = True
    acceptance_criteria: list[str] = Field(default_factory=list)
    delivery_format: str | None = None
    destination_folder: str | None = None
    metadata: dict[str, Any] = Field(default_factory=dict)


class RemediationTaskItem(BaseModel):
    """Một bước công việc trong baseline remediation plan."""

    task_id: str
    task_code: str
    title: str
    description: str | None = None
    task_type: str
    status: str = "pending"
    priority: str = "medium"
    sequence_no: int = 1
    owner_department_code: str | None = None
    owner_employee_code: str | None = None
    dependency_task_ids: list[str] = Field(default_factory=list)
    expected_output_codes: list[str] = Field(default_factory=list)
    blocking: bool = False
    metadata: dict[str, Any] = Field(default_factory=dict)


class RemediationReadinessSummary(BaseModel):
    """Tóm tắt mức sẵn sàng và các điểm nghẽn của phương án khắc phục."""

    status: str = "blocked"
    ready_input_count: int = 0
    missing_input_count: int = 0
    blocking_input_count: int = 0
    artifact_count: int = 0
    task_count: int = 0
    blocking_reasons: list[str] = Field(default_factory=list)
    coverage_gap_count: int = 0
    message: str | None = None


class RemediationPlanItem(BaseModel):
    """Phương án khắc phục machine-readable cho một dossier finding."""

    plan_id: str
    project_code: str
    review_session_id: str
    finding_id: str
    finding_code: str | None = None
    document_type: str
    dossier_stage: str | None = None
    priority: str = "medium"
    owner_department_code: str | None = None
    owner_employee_code: str | None = None
    destination_folder: str
    output_filename: str
    naming_rule: str
    required_inputs: list[RemediationRequiredInputItem] = Field(default_factory=list)
    artifact_requirements: list[RemediationArtifactRequirementItem] = Field(
        default_factory=list
    )
    remediation_tasks: list[RemediationTaskItem] = Field(default_factory=list)
    readiness_summary: RemediationReadinessSummary
    source: str = "derived"
    used_fallback: bool = False
    message: str | None = None
    metadata: dict[str, Any] = Field(default_factory=dict)


class RemediationBuildRequest(BaseModel):
    """Request payload để build một remediation plan tường minh."""

    project_code: str = Field(..., min_length=1)
    review_session_id: str | None = None
    finding_id: str | None = None
    finding_code: str | None = None
    document_type: str | None = None

    @model_validator(mode="after")
    def ensure_finding_selector(self) -> RemediationBuildRequest:
        """Yêu cầu ít nhất một selector để xác định finding cần build plan."""
        if not any(
            [
                self.finding_id and self.finding_id.strip(),
                self.finding_code and self.finding_code.strip(),
                self.document_type and self.document_type.strip(),
            ]
        ):
            raise ValueError(
                "Cần cung cấp finding_id, finding_code hoặc document_type để build remediation plan."
            )
        return self


class RemediationBuildResponse(BaseModel):
    """Response payload cho thao tác build một remediation plan."""

    item: RemediationPlanItem | None = None
    source: str = "fallback"
    used_fallback: bool = False
    message: str | None = None


class RemediationGapItem(BaseModel):
    """Một readiness/remediation gap được chuẩn hóa từ dossier review findings."""

    project_code: str
    review_session_id: str
    finding_id: str
    finding_code: str | None = None
    document_type: str | None = None
    dossier_stage: str | None = None
    priority: str = "medium"
    owner_department_code: str | None = None
    owner_employee_code: str | None = None
    gap_status: str = "blocked"
    blocking_reasons: list[str] = Field(default_factory=list)
    missing_input_codes: list[str] = Field(default_factory=list)
    missing_input_labels: list[str] = Field(default_factory=list)
    requires_document_type_mapping: bool = False
    can_build_plan: bool = False
    plan_id: str | None = None
    suggested_task_type: str | None = None
    source: str = "derived"
    used_fallback: bool = False
    metadata: dict[str, Any] = Field(default_factory=dict)


class RemediationGapsResponse(BaseModel):
    """Danh sách readiness/remediation gaps suy ra từ review findings."""

    items: list[RemediationGapItem] = Field(default_factory=list)
    source: str = "fallback"
    used_fallback: bool = False
    message: str | None = None


class RemediationListResponse(BaseModel):
    """Danh sách remediation plans suy diễn từ dossier review sessions."""

    items: list[RemediationPlanItem] = Field(default_factory=list)
    source: str = "fallback"
    used_fallback: bool = False
    message: str | None = None


class RemediationPlanSummaryItem(BaseModel):
    """Tóm tắt remediation plan để nhúng vào operational state hoặc dashboard."""

    project_code: str
    review_session_id: str
    finding_id: str
    finding_code: str | None = None
    document_type: str
    dossier_stage: str | None = None
    priority: str = "medium"
    owner_department_code: str | None = None
    owner_employee_code: str | None = None
    readiness_status: str = "blocked"
    blocking_reasons: list[str] = Field(default_factory=list)
    destination_folder: str | None = None
    output_filename: str | None = None
    source: str = "derived"
    used_fallback: bool = False
    message: str | None = None
