from __future__ import annotations

import re
from pathlib import Path

from .config import EXPECTED_DOCUMENT_TYPES, INGEST_BATCH, ROOT_DIR, SOURCE_CODE
from .helpers import normalize_relative_path
from .models import DocumentTypeRule, ProjectCandidate, ProjectDocument


def build_document_type_rules() -> list[DocumentTypeRule]:
    raw_rules = [
        DocumentTypeRule(
            "quyet_dinh_phe_duyet_nhiem_vu",
            "nhiem vu",
            "any",
            10,
            "project_approval",
            "decision_document",
            "pre_award",
            "decision",
            ("pre_award",),
            "Quyết định phê duyệt nhiệm vụ",
        ),
        DocumentTypeRule(
            "quyet_dinh_phe_duyet_bcktkt",
            "bcktkt",
            "any",
            10,
            "project_approval",
            "decision_document",
            "pre_award",
            "decision",
            ("pre_award",),
            "Quyết định phê duyệt BCKTKT",
        ),
        DocumentTypeRule(
            "quyet_dinh_phe_duyet_khlcnt",
            "khlcnt",
            "any",
            10,
            "procurement_tender",
            "decision_document",
            "pre_award",
            "decision",
            ("pre_award", "contracting"),
            "Quyết định phê duyệt KHLCNT",
        ),
        DocumentTypeRule(
            "quyet_dinh_phe_duyet_kqlcnt",
            "kqlcnt",
            "any",
            10,
            "procurement_tender",
            "decision_document",
            "contracting",
            "decision",
            ("contracting",),
            "Quyết định phê duyệt KQLCNT",
        ),
        DocumentTypeRule(
            "bien_ban_thuong_thao_hop_dong",
            "thuong thao",
            "any",
            20,
            "contract_management",
            "negotiation_record",
            "contracting",
            "contract",
            ("contracting",),
            "Biên bản thương thảo hợp đồng",
        ),
        DocumentTypeRule(
            "phu_luc_hop_dong",
            "phu luc hop dong",
            "any",
            20,
            "contract_management",
            "contract_document",
            "contracting",
            "contract",
            ("contracting", "payment", "finalization"),
            "Phụ lục hợp đồng",
        ),
        DocumentTypeRule(
            "hop_dong_thi_cong",
            "hop dong",
            "any",
            30,
            "contract_management",
            "contract_document",
            "contracting",
            "contract",
            ("contracting", "payment", "finalization"),
            "Hợp đồng thi công",
        ),
        DocumentTypeRule(
            "bao_lanh_thuc_hien_hop_dong",
            "bao lanh thuc hien",
            "any",
            15,
            "contract_management",
            "guarantee_document",
            "contracting",
            "guarantee",
            ("contracting",),
            "Bảo lãnh thực hiện hợp đồng",
        ),
        DocumentTypeRule(
            "bao_lanh_tam_ung",
            "bao lanh tam ung",
            "any",
            15,
            "payment_support",
            "guarantee_document",
            "payment",
            "guarantee",
            ("payment",),
            "Bảo lãnh tạm ứng",
        ),
        DocumentTypeRule(
            "ban_ve_hoan_cong",
            "hoan cong",
            "any",
            10,
            "closeout_documentation",
            "as_built_drawing",
            "finalization",
            "drawing",
            ("finalization",),
            "Bản vẽ hoàn công",
        ),
        DocumentTypeRule(
            "ho_so_hoan_cong",
            "ho so hoan cong",
            "any",
            5,
            "closeout_documentation",
            "as_built_record",
            "finalization",
            "closeout",
            ("finalization",),
            "Hồ sơ hoàn công",
        ),
        DocumentTypeRule(
            "ban_ve_chi_tiet",
            "chi tiet",
            "filename",
            20,
            "technical_delivery",
            "technical_drawing",
            "execution",
            "drawing",
            ("execution", "payment"),
            "Bản vẽ chi tiết",
        ),
        DocumentTypeRule(
            "ban_ve_thi_cong",
            "bd_",
            "filename",
            20,
            "technical_delivery",
            "technical_drawing",
            "execution",
            "drawing",
            ("execution", "payment"),
            "Bản vẽ thi công",
        ),
        DocumentTypeRule(
            "ban_ve_thi_cong",
            "ban ve",
            "any",
            25,
            "technical_delivery",
            "technical_drawing",
            "execution",
            "drawing",
            ("execution", "payment"),
            "Bản vẽ thi công",
        ),
        DocumentTypeRule(
            "du_toan",
            "du toan",
            "any",
            20,
            "cost_management",
            "estimate_document",
            "pre_award",
            "cost",
            ("pre_award", "contracting"),
            "Dự toán",
        ),
        DocumentTypeRule(
            "bang_khoi_luong",
            "khoi luong",
            "any",
            20,
            "cost_management",
            "quantity_table",
            "payment",
            "cost",
            ("payment",),
            "Bảng khối lượng",
        ),
        DocumentTypeRule(
            "bien_ban_ban_giao_mat_bang",
            "ban giao mat bang",
            "any",
            20,
            "site_handover",
            "handover_record",
            "execution",
            "handover",
            ("execution",),
            "Biên bản bàn giao mặt bằng",
        ),
        DocumentTypeRule(
            "nhat_ky_thi_cong",
            "nhat ky",
            "any",
            20,
            "site_execution",
            "site_log",
            "execution",
            "execution_record",
            ("execution",),
            "Nhật ký thi công",
        ),
        DocumentTypeRule(
            "ho_so_quan_ly_chat_luong",
            "chat luong",
            "any",
            20,
            "quality_management",
            "quality_record",
            "execution",
            "quality",
            ("execution", "finalization"),
            "Hồ sơ quản lý chất lượng",
        ),
        DocumentTypeRule(
            "bien_ban_nghiem_thu_cong_viec",
            "nghiem thu",
            "any",
            20,
            "payment_support",
            "acceptance_record",
            "payment",
            "acceptance",
            ("payment", "finalization"),
            "Biên bản nghiệm thu công việc",
        ),
        DocumentTypeRule(
            "ho_so_thanh_toan",
            "thanh toan",
            "any",
            20,
            "payment_support",
            "payment_document",
            "payment",
            "payment",
            ("payment",),
            "Hồ sơ thanh toán",
        ),
        DocumentTypeRule(
            "bang_gia_tri_thanh_toan",
            "gia tri thanh toan",
            "any",
            15,
            "payment_support",
            "payment_value_table",
            "payment",
            "payment",
            ("payment",),
            "Bảng giá trị thanh toán",
        ),
        DocumentTypeRule(
            "ho_so_quyet_toan_tong_hop",
            "quyet toan",
            "any",
            20,
            "closeout_documentation",
            "settlement_document",
            "finalization",
            "settlement",
            ("finalization",),
            "Hồ sơ quyết toán tổng hợp",
        ),
        DocumentTypeRule(
            "bien_ban_thanh_ly_hop_dong",
            "thanh ly",
            "any",
            20,
            "closeout_documentation",
            "liquidation_record",
            "finalization",
            "settlement",
            ("finalization",),
            "Biên bản thanh lý hợp đồng",
        ),
    ]
    return sorted(raw_rules, key=lambda item: item.priority)


def validate_project_candidates(candidates: list[ProjectCandidate]) -> None:
    seen_codes: set[str] = set()
    duplicates: set[str] = set()
    for candidate in candidates:
        if candidate.project_code in seen_codes:
            duplicates.add(candidate.project_code)
        seen_codes.add(candidate.project_code)
    if duplicates:
        raise ValueError(
            f"Duplicate project_code values found: {', '.join(sorted(duplicates))}"
        )


def extract_project_root(candidate: ProjectCandidate) -> Path | None:
    match = re.search(r"Nguồn:\s*(.+)$", candidate.notes)
    if not match:
        return None
    path = Path(match.group(1).strip())
    return path if path.exists() else None


def classify_project_file(
    path: Path, project_root: Path, rules: list[DocumentTypeRule]
) -> tuple[str, str | None, float, DocumentTypeRule | None]:
    relative_path = path.relative_to(project_root)
    normalized_path = normalize_relative_path(relative_path)
    normalized_name = normalize_relative_path(path.name)
    normalized_parent = normalize_relative_path(relative_path.parent)

    for rule in rules:
        target = normalized_path
        if rule.match_scope == "filename":
            target = normalized_name
        elif rule.match_scope == "folder":
            target = normalized_parent
        if rule.pattern in target:
            confidence = 0.95 if rule.match_scope != "any" else 0.88
            return rule.document_type, rule.pattern, confidence, rule

    if path.suffix.lower() == ".pdf" and "bd" in normalized_name:
        for rule in rules:
            if rule.document_type == "ban_ve_thi_cong":
                return rule.document_type, "fallback:bd", 0.72, rule
    return "unknown", None, 0.0, None


def build_project_document(
    candidate: ProjectCandidate,
    project_root: Path,
    path: Path,
    rules: list[DocumentTypeRule],
) -> ProjectDocument:
    document_type, matched_rule, confidence, rule = classify_project_file(
        path, project_root, rules
    )
    relative_path = path.relative_to(ROOT_DIR)
    default_section_title = path.stem

    if rule is None:
        return ProjectDocument(
            project_code=candidate.project_code,
            project_name=candidate.project_name,
            project_root=str(project_root),
            absolute_path=path,
            relative_path=str(relative_path),
            source_filename=path.name,
            source_format=path.suffix.lower().lstrip("."),
            folder_scope=str(path.parent.relative_to(ROOT_DIR)),
            document_type=document_type,
            classification_source="rule_based_fallback",
            matched_rule=matched_rule,
            confidence=confidence,
            task_type="dossier_inventory",
            knowledge_type="unclassified_document",
            doc_stage="unclassified",
            doc_family="unknown",
            required_for=(),
            section_title=default_section_title,
            issuer="",
            signer="",
            tags=("unknown", "needs_review"),
            compliance_refs=("Cần rà soát và phân loại thủ công bổ sung.",),
            readiness_weight=0.0,
        )

    return ProjectDocument(
        project_code=candidate.project_code,
        project_name=candidate.project_name,
        project_root=str(project_root),
        absolute_path=path,
        relative_path=str(relative_path),
        source_filename=path.name,
        source_format=path.suffix.lower().lstrip("."),
        folder_scope=str(path.parent.relative_to(ROOT_DIR)),
        document_type=rule.document_type,
        classification_source="rule_based",
        matched_rule=matched_rule,
        confidence=confidence,
        task_type=rule.task_type,
        knowledge_type=rule.knowledge_type,
        doc_stage=rule.doc_stage,
        doc_family=rule.doc_family,
        required_for=rule.required_for,
        section_title=rule.section_title,
        issuer=rule.issuer,
        signer=rule.signer,
        tags=(rule.document_type, rule.doc_stage, rule.doc_family),
        compliance_refs=(rule.description,) if rule.description else (),
        readiness_weight=0.8 if rule.doc_stage == "contracting" else 0.7,
    )


def build_project_coverage_manifest(
    candidate: ProjectCandidate,
    documents: list[ProjectDocument],
    ingest_summary: dict[str, object],
    project_root: Path | None,
) -> dict[str, object]:
    document_type_counts: dict[str, int] = {}
    classified_files = 0
    unknown_files = 0
    sample_unknown_files: list[str] = []

    for document in documents:
        document_type_counts[document.document_type] = (
            document_type_counts.get(document.document_type, 0) + 1
        )
        if document.document_type == "unknown":
            unknown_files += 1
            if len(sample_unknown_files) < 10:
                sample_unknown_files.append(document.relative_path)
        else:
            classified_files += 1

    discovered = {
        doc_type for doc_type in document_type_counts if doc_type != "unknown"
    }
    missing_document_types = sorted(
        doc_type for doc_type in EXPECTED_DOCUMENT_TYPES if doc_type not in discovered
    )

    return {
        "project_code": candidate.project_code,
        "project_name": candidate.project_name,
        "project_root": str(project_root) if project_root else None,
        "project_root_exists": bool(project_root and project_root.exists()),
        "total_files": len(documents),
        "extractable_files": len(documents),
        "classified_files": classified_files,
        "unknown_files": unknown_files,
        "knowledge_files_ingested": ingest_summary.get("files_ingested", 0),
        "knowledge_chunks_ingested": ingest_summary.get("chunks", 0),
        "document_type_counts": document_type_counts,
        "missing_document_types": missing_document_types,
        "sample_unknown_files": sample_unknown_files,
        "sample_skipped_files": ingest_summary.get("skipped_files", []),
        "missing_files": ingest_summary.get("missing_files", []),
        "ingested_document_types": ingest_summary.get("document_types", []),
        "stages": ingest_summary.get("stages", []),
        "ingest_batch": INGEST_BATCH,
        "source_code": SOURCE_CODE,
    }
