from __future__ import annotations

import logging
from typing import Any

from app.core.postgres.erp_client import ErpDatabaseClient

from .models import QSDrillScorecard, TakeoffItemEvaluation

logger = logging.getLogger("dscons.takeoff_training.synthesizer")


class QSRuleSynthesizer:
    """Tự động trích xuất bài học kinh nghiệm (Learned Rules) từ sai số bóc tách và nạp vào DB."""

    @classmethod
    def synthesize_and_save_rules(
        cls,
        scorecard: QSDrillScorecard,
        db_client: ErpDatabaseClient | None = None,
    ) -> list[dict[str, Any]]:
        """Phân tích các lỗi sai số và tự động sinh quy tắc rút kinh nghiệm cho AI Quỳnh."""
        client = db_client or ErpDatabaseClient()
        synthesized: list[dict[str, Any]] = []

        major_errors = [
            item
            for item in scorecard.evaluated_items
            if item.match_status in ("MAJOR_DEVIATION", "MISSED")
        ]

        for err in major_errors[:5]:  # Process top 5 most impactful errors per epoch
            category = cls._infer_category(err.task_name)
            drawing_type = cls._infer_drawing_type(
                err.task_name, scorecard.project_name
            )
            trigger = f"Bóc tách công tác '{err.task_name}' (ĐVT: {err.unit}) bị sai lệch {err.deviation_pct}% so với chuẩn Kỹ sư."
            directive = cls._generate_correction_directive(err)

            rule_payload = {
                "rule_title": f"Tự Học [{scorecard.project_code}]: Hiệu chỉnh bóc {err.task_name[:40]}",
                "drawing_type": drawing_type,
                "rule_category": category,
                "trigger_pattern": trigger,
                "correction_directive": directive,
                "confidence_score": 0.95,
                "learned_from_project_id": scorecard.project_code,
                "status": "APPROVED",
            }

            try:
                saved = client.save_learned_rule(
                    rule_title=rule_payload["rule_title"],
                    drawing_type=rule_payload["drawing_type"],
                    rule_category=rule_payload["rule_category"],
                    trigger_pattern=rule_payload["trigger_pattern"],
                    correction_directive=rule_payload["correction_directive"],
                    confidence_score=rule_payload["confidence_score"],
                    learned_from_project_id=rule_payload["learned_from_project_id"],
                    status="APPROVED",
                )
                synthesized.append(saved or rule_payload)
                logger.info(
                    "[QS_SYNTHESIZER] Saved new learned rule: %s",
                    rule_payload["rule_title"],
                )
            except Exception as exc:
                logger.warning("[QS_SYNTHESIZER] Failed saving rule: %s", exc)
                synthesized.append(rule_payload)

        return synthesized

    @staticmethod
    def _infer_category(task_name: str) -> str:
        t = task_name.lower()
        if "bê tông" in t or "btct" in t:
            return "CONCRETE_VOLUME"
        elif "ván khuôn" in t or "cốp pha" in t:
            return "FORMWORK_AREA"
        elif "cốt thép" in t or "thép" in t:
            return "REBAR_WEIGHT"
        elif "đào" in t or "đắp" in t or "vận chuyển đất" in t:
            return "EARTHWORK_VOLUME"
        elif "phá dỡ" in t or "đục tẩy" in t or "cạo bỏ" in t:
            return "DEMOLITION_RENOVATION"
        return "GENERAL_ESTIMATE"

    @staticmethod
    def _infer_drawing_type(task_name: str, project_name: str) -> str:
        p = project_name.lower()
        t = task_name.lower()
        if "cống" in p or "mương" in p or "kênh" in p:
            return "IRRIGATION_HYDRAULIC"
        elif "đường" in p or "giao thông" in p or "nền" in p:
            return "ROAD_INFRASTRUCTURE"
        elif "kết cấu" in t or "móng" in t or "cột" in t or "dầm" in t or "sàn" in t:
            return "STRUCTURAL_CONCRETE"
        return "ARCHITECTURAL_CIVIL"

    @staticmethod
    def _generate_correction_directive(err: TakeoffItemEvaluation) -> str:
        t = err.task_name.lower()
        if "phá dỡ" in t or "đục tẩy" in t or "cạo" in t:
            return f"Bóc tách công tác hoàn thiện cải tạo '{err.task_name}': Chia tách theo từng diện tích bề mặt (sân khấu, hội trường, chân móng, trần hiên), trừ chính xác diện tích cửa đi/cửa sổ và áp dụng tỷ lệ % hư hỏng thực tế (10% - 90%)."
        elif "bê tông" in t:
            return f"Khi bóc bê tông '{err.task_name}': Tính toán hình học chi tiết từng cấu kiện (Dài * Rộng * Cao * Số lượng) và bắt buộc trừ thể tích phần cọc bê tông/cấu kiện giao nhau."
        elif "ván khuôn" in t:
            return f"Khi bóc ván khuôn '{err.task_name}': Tính diện tích tiếp xúc thực tế giữa bê tông và ván khuôn, bổ sung ván khuôn thành bên và ván khuôn đầu mang cống."
        elif "thép" in t:
            return f"Khi bóc cốt thép '{err.task_name}': Tính tổng chiều dài bao gồm đoạn neo 30d/40d và đoạn nối chồng 30d, nhân trọng lượng riêng kg/m theo đường kính thanh."
        return f"Hiệu chỉnh bóc tách công tác '{err.task_name}': Áp dụng công thức phân rã chi tiết kích thước theo đúng định mức Thông tư 12/2021/TT-BXD và Thông tư 2026."
