"""
Inverse-BIM & Tri-Source Truth Grounding Mixin for DrawingTakeoffService.
Provides high-level orchestration methods for parametric constraint solving
and 3-way truth reconciliation.
"""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Any, Optional

from app.modules.takeoff.application.inverse_bim_constraint_solver import (
    InverseBimConstraintSolver,
)
from app.modules.takeoff.application.tri_source_truth_grounding import (
    TriSourceTruthGrounding,
)
from app.modules.takeoff.domain.inverse_bim_models import (
    InverseBimParametricModel,
    SolidTakeoffQuantities,
    TriSourceAuditReport,
)

logger = logging.getLogger(__name__)

BEN_KEM_BASE_DIR = Path(
    "CongTrinh/HĐ-2026/Kiến Minh-2026/Hệ thống cống hộp kênh bến Kem. ok"
)
DEFAULT_DXF = BEN_KEM_BASE_DIR / "BV + DT MUONG THOAT ben kem/02. Thiet ke dong khung.dxf"
DEFAULT_KC_PDF = (
    BEN_KEM_BASE_DIR / "Đấu Thầu/File_IB2600072041/Bản vẽ/03. kc cong.pdf"
)
DEFAULT_HSMT_XLSX = (
    BEN_KEM_BASE_DIR / "Thẩm định/cống hộp bến kem.21.02.2026.TĐ.xlsx"
)


class DrawingInverseBimMixin:
    """Mixin adding Inverse-BIM and Tri-Source Truth Grounding capabilities."""

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        self._inverse_bim_solver = InverseBimConstraintSolver()
        self._tri_source_engine = TriSourceTruthGrounding()

    def solve_inverse_bim_constraints(
        self,
        cad_source: str | Path | None = None,
        **kwargs: Any,
    ) -> dict[str, Any]:
        """Extract parametric constraints and compute deterministic solid volumes."""
        solver = getattr(self, "_inverse_bim_solver", None) or InverseBimConstraintSolver()
        src = Path(cad_source) if cad_source else DEFAULT_DXF
        if not src.exists():
            src = DEFAULT_KC_PDF

        model: InverseBimParametricModel = solver.extract_parametric_constraints(src, **kwargs)
        solids: SolidTakeoffQuantities = solver.compute_deterministic_solids(model)

        return {
            "status": "success",
            "parametric_model": model.model_dump(),
            "solids": solids.model_dump(),
        }

    def run_tri_source_reconciliation(
        self,
        cad_source: str | Path | None = None,
        bbs_source: str | Path | None = None,
        hsmt_source: str | Path | None = None,
        project_name: str = "XÂY DỰNG HỆ THỐNG CỐNG HỘP KÊNH BẾN KEM, XÃ KIẾN MINH",
        package_name: str = "Gói thầu số 6: Gói thầu xây lắp",
    ) -> TriSourceAuditReport:
        """Execute end-to-end 3-way cross-audit between CAD geometry, BBS schedule, and HSMT tender BoQ."""
        solver = getattr(self, "_inverse_bim_solver", None) or InverseBimConstraintSolver()
        engine = getattr(self, "_tri_source_engine", None) or TriSourceTruthGrounding()

        cad_path = Path(cad_source) if cad_source else DEFAULT_DXF
        if not cad_path.exists():
            cad_path = DEFAULT_KC_PDF

        bbs_path = Path(bbs_source) if bbs_source else DEFAULT_KC_PDF
        hsmt_path = Path(hsmt_source) if hsmt_source else DEFAULT_HSMT_XLSX

        # 1. Source A: CAD Geometric Solids
        model = solver.extract_parametric_constraints(cad_path)
        solids = solver.compute_deterministic_solids(model)

        # 2. Source B: BBS Rebar Schedule
        bbs_items = engine.extract_bbs_schedule(bbs_path)

        # 3. Source C: Statutory Tender BoQ
        hsmt_items = engine.extract_hsmt_tender_items(hsmt_path)

        # 4. Tri-Source Reconciliation
        report = engine.reconcile_tri_source(
            solids=solids,
            bbs_items=bbs_items,
            hsmt_items=hsmt_items,
            project_name=project_name,
            package_name=package_name,
        )

        return report
