from __future__ import annotations

from typing import Any

from app.models.schemas import (
    RemediationGapItem,
    RemediationReadinessSummary,
    RemediationTaskItem,
)

from .plan_items import RemediationCoverageGap


def build_remediation_tasks(
    service: Any,
    *,
    session: dict[str, Any],
    finding: dict[str, Any],
    priority: str,
    owner_department_code: str | None,
    owner_employee_code: str | None,
) -> list[RemediationTaskItem]:
    """Tạo remediation task."""
    document_type = str(finding.get("document_type") or "").strip()
    plan_id = service._build_plan_id(
        review_id=str(session.get("review_id") or ""), finding=finding
    )
    if document_type == "bien_ban_nghiem_thu_noi_bo":
        return [
            service._task_item(
                plan_id=plan_id,
                task_code="thu_thap_dau_vao_nghiem_thu",
                title="Thu thập đầu vào nghiệm thu nội bộ",
                description="Tập hợp thông tin hạng mục, căn cứ hồ sơ chất lượng, ngày nghiệm thu và thành phần tham dự.",
                task_type="data_collection",
                sequence_no=1,
                priority=priority,
                owner_department_code=owner_department_code,
                owner_employee_code=owner_employee_code,
                expected_output_codes=["ban_du_thao_bien_ban"],
                blocking=True,
            ),
            service._task_item(
                plan_id=plan_id,
                task_code="lap_du_thao_bien_ban",
                title="Lập dự thảo biên bản nghiệm thu nội bộ",
                description="Soạn biên bản theo mẫu nội bộ, ghi rõ kết quả kiểm tra, tồn tại và kiến nghị xử lý.",
                task_type="document_drafting",
                sequence_no=2,
                priority=priority,
                owner_department_code=owner_department_code,
                owner_employee_code=owner_employee_code,
                dependency_task_codes=["thu_thap_dau_vao_nghiem_thu"],
                expected_output_codes=["ban_du_thao_bien_ban"],
                blocking=True,
            ),
            service._task_item(
                plan_id=plan_id,
                task_code="bo_sung_minh_chung_hien_truong",
                title="Bổ sung minh chứng hiện trường",
                description="Đính kèm ảnh hiện trường, checklist hoặc hồ sơ chất lượng làm căn cứ nghiệm thu.",
                task_type="evidence_packaging",
                sequence_no=3,
                priority=priority,
                owner_department_code=owner_department_code,
                owner_employee_code=owner_employee_code,
                dependency_task_codes=["thu_thap_dau_vao_nghiem_thu"],
                expected_output_codes=["bo_minh_chung_dinh_kem"],
                blocking=False,
            ),
            service._task_item(
                plan_id=plan_id,
                task_code="trinh_ky_xac_nhan",
                title="Trình ký xác nhận nghiệm thu nội bộ",
                description="Chuyển dự thảo và minh chứng sang luồng ký/xác nhận của các thành phần tham dự.",
                task_type="approval_routing",
                sequence_no=4,
                priority=priority,
                owner_department_code=owner_department_code,
                owner_employee_code=owner_employee_code,
                dependency_task_codes=[
                    "lap_du_thao_bien_ban",
                    "bo_sung_minh_chung_hien_truong",
                ],
                expected_output_codes=["ban_ky_xac_nhan"],
                blocking=True,
            ),
        ]
    return [
        service._task_item(
            plan_id=plan_id,
            task_code="xac_dinh_du_lieu_nguon",
            title=f"Xác định dữ liệu nguồn cho {document_type}",
            description="Rà soát finding, metadata và hồ sơ dự án để xác định bộ dữ liệu đầu vào tối thiểu.",
            task_type="triage",
            sequence_no=1,
            priority=priority,
            owner_department_code=owner_department_code,
            owner_employee_code=owner_employee_code,
            expected_output_codes=["tai_lieu_khac_phuc"],
            blocking=True,
        ),
        service._task_item(
            plan_id=plan_id,
            task_code="tao_tai_lieu_khac_phuc",
            title=f"Tạo tài liệu khắc phục cho {document_type}",
            description="Lập tài liệu theo naming rule, lưu đúng thư mục gợi ý và sẵn sàng gửi xác minh.",
            task_type="document_drafting",
            sequence_no=2,
            priority=priority,
            owner_department_code=owner_department_code,
            owner_employee_code=owner_employee_code,
            dependency_task_codes=["xac_dinh_du_lieu_nguon"],
            expected_output_codes=["tai_lieu_khac_phuc"],
            blocking=True,
        ),
    ]


def build_readiness_summary(
    service: Any,
    *,
    session: dict[str, Any],
    finding: dict[str, Any],
    required_inputs: list[RemediationRequiredInputItem],
    artifact_requirements: list[RemediationArtifactRequirementItem],
    remediation_tasks: list[RemediationTaskItem],
    coverage_project: dict[str, Any] | None,
) -> RemediationReadinessSummary:
    """Tóm tắt readiness."""
    ready_input_count = sum(1 for item in required_inputs if item.status == "ready")
    missing_inputs = [item for item in required_inputs if item.status != "ready"]
    blocking_inputs = [item for item in missing_inputs if item.blocking]
    blocking_reasons = [f"Thiếu input: {item.label}" for item in blocking_inputs]
    coverage_gaps = service._derive_coverage_blocking_reasons(
        project_code=str(session.get("project_code") or ""),
        document_type=str(finding.get("document_type") or ""),
        coverage_project=coverage_project,
    )
    coverage_blocking_gaps = [gap for gap in coverage_gaps if gap.blocking]
    blocking_reasons.extend(gap.message for gap in coverage_blocking_gaps)
    supplement_status = str(finding.get("supplement_status") or "").strip().lower()
    if (
        supplement_status in {"requested", "collecting", "not_requested"}
        and not required_inputs
    ):
        blocking_reasons.append("Chưa xác định được bộ input tối thiểu cho finding.")
    has_any_coverage_gaps = bool(coverage_gaps)
    has_blocking_coverage_gaps = bool(coverage_blocking_gaps)
    if not missing_inputs and not has_any_coverage_gaps:
        status = "ready"
        message = "Đủ input để bắt đầu remediation."
    elif blocking_inputs or has_blocking_coverage_gaps:
        status = "blocked"
        message = "Cần bổ sung input hoặc xử lý coverage gaps chặn trước khi hoàn thiện hồ sơ khắc phục."
    else:
        status = "needs_review"
        message = "Có thể tiếp tục remediation nhưng cần rà soát coverage gaps không chặn và xác nhận hồ sơ."
    return RemediationReadinessSummary(
        status=status,
        ready_input_count=ready_input_count,
        missing_input_count=len(missing_inputs),
        blocking_input_count=len(blocking_inputs),
        artifact_count=len(artifact_requirements),
        task_count=len(remediation_tasks),
        blocking_reasons=blocking_reasons,
        coverage_gap_count=len(coverage_gaps),
        message=message,
    )


def build_plan_message(
    *, document_type: str, readiness_summary: RemediationReadinessSummary
) -> str:
    """Tạo message plan."""
    if document_type == "bien_ban_nghiem_thu_noi_bo":
        return f"Đã áp dụng baseline chuyên biệt cho biên bản nghiệm thu nội bộ; trạng thái readiness: {readiness_summary.status}."
    return f"Đã áp dụng baseline remediation fallback an toàn cho document_type chưa có playbook chuyên biệt; trạng thái readiness: {readiness_summary.status}."


def build_gap_item(service: Any, plan: RemediationPlanItem) -> RemediationGapItem:
    """Đổi plan sang gap."""
    missing_inputs = [item for item in plan.required_inputs if item.status != "ready"]
    return RemediationGapItem(
        project_code=plan.project_code,
        review_session_id=plan.review_session_id,
        finding_id=plan.finding_id,
        finding_code=plan.finding_code,
        document_type=plan.document_type,
        dossier_stage=plan.dossier_stage,
        priority=plan.priority,
        owner_department_code=plan.owner_department_code,
        owner_employee_code=plan.owner_employee_code,
        gap_status=plan.readiness_summary.status,
        blocking_reasons=list(plan.readiness_summary.blocking_reasons),
        missing_input_codes=[item.input_code for item in missing_inputs],
        missing_input_labels=[item.label for item in missing_inputs],
        requires_document_type_mapping=plan.used_fallback,
        can_build_plan=plan.readiness_summary.status != "blocked",
        plan_id=plan.plan_id,
        suggested_task_type=service._suggest_task_type(plan.document_type),
        source=plan.source,
        used_fallback=plan.used_fallback,
        metadata={
            "output_filename": plan.output_filename,
            "destination_folder": plan.destination_folder,
            "coverage_gap_count": plan.readiness_summary.coverage_gap_count,
        },
    )


def derive_coverage_blocking_reasons(
    *,
    project_code: str,
    document_type: str,
    coverage_project: dict[str, Any] | None,
) -> list[RemediationCoverageGap]:
    """Đổi coverage thành gap."""
    if coverage_project is None:
        return [
            RemediationCoverageGap(
                message="Chưa có coverage manifest cho dự án; cần chạy ingest/coverage inspection trước khi đóng finding.",
                blocking=False,
            )
        ]
    missing_types = {
        str(item).strip()
        for item in coverage_project.get("missing_document_types", [])
        if str(item).strip()
    }
    reasons: list[RemediationCoverageGap] = []
    if document_type in missing_types:
        reasons.append(
            RemediationCoverageGap(
                message=f"Coverage manifest ghi nhận còn thiếu document_type {document_type} trong hồ sơ dự án.",
                blocking=False,
            )
        )
    unknown_files = int(coverage_project.get("unknown_files", 0) or 0)
    if unknown_files > 0:
        reasons.append(
            RemediationCoverageGap(
                message=f"Còn {unknown_files} file chưa phân loại trong coverage manifest; cần rà soát mapping document_type.",
                blocking=True,
            )
        )
    return reasons
