from __future__ import annotations

"""Automated test suite for Thông tư 38/2026/TT-BXD Construction Norms, Sheet Piling (AC.22111, AC.22112), and Bamboo Piling (AC.11110)."""

import uuid
from pathlib import Path

from fastapi.testclient import TestClient

from app.core.postgres.erp_client import ErpDatabaseClient
from app.main import app
from app.modules.takeoff.application.vision_prompts import get_vision_system_prompt
from app.modules.takeoff.application.boq_rate_breakdown_service import BoqRateBreakdownEngine
from app.modules.takeoff.application.learning_prompts import (
    build_quynh_fallback_response,
    build_quynh_system_prompt,
)

AUTH_HEADERS = {"Authorization": "Bearer dev-test-token"}


def test_thong_tu_38_knowledge_base_file_exists_and_metadata():
    """Kiểm tra văn bản Thông tư 38/2026/TT-BXD đã được nạp đầy đủ vào Knowledge Base theo chuẩn Rule 4."""
    kb_path = Path(
        "KNOWLEDGE_BASE/LAW/THONG_TU/Thong_Tu_38_2026_TT_BXD_Dinh_Muc_Du_Toan_Xay_Dung.md"
    )
    assert kb_path.exists(), (
        "Tệp Thông tư 38/2026/TT-BXD không tồn tại trong KNOWLEDGE_BASE!"
    )

    content = kb_path.read_text(encoding="utf-8")
    assert "38/2026/TT-BXD" in content
    assert "AC.22111" in content
    assert "AC.22112" in content
    assert "AC.11110" in content
    assert "cọc tre" in content
    assert "Larsen" in content


def test_boq_breakdown_engine_larsen_sheet_piling_norms():
    """Kiểm tra động cơ phân rã đơn giá tự động gán mã AC.22111 (ép cừ) và AC.22112 (nhổ cừ) theo TT 38/2026/TT-BXD."""
    # 1. Ép cọc cừ thép Larsen IV
    res_ep = BoqRateBreakdownEngine.breakdown_item_rate(
        item_name="Ép cọc cừ thép Larsen IV L=12m gia cố hố móng bằng búa rung",
        category="foundation",
        unit="md",
        total_unit_price=95000.0,
    )
    assert res_ep["norm_code"] == "AC.22111"
    assert res_ep["material_cost_vnd"] > 0
    assert res_ep["labor_cost_vnd"] > 0
    assert res_ep["equipment_cost_vnd"] > 0

    # Kiểm tra chi phí thuê cừ luân chuyển trong vật tư
    mats_ep = res_ep["material_breakdown"]
    assert any(
        "THUE-CU-LARSEN" in m["material_code"] or "Larsen" in m["material_name"]
        for m in mats_ep
    )

    # 2. Nhổ cọc cừ thép Larsen IV
    res_nho = BoqRateBreakdownEngine.breakdown_item_rate(
        item_name="Nhổ cọc cừ thép Larsen IV sau khi hoàn thành kết cấu hố móng",
        category="foundation",
        unit="md",
        total_unit_price=45000.0,
    )
    assert res_nho["norm_code"] == "AC.22112"
    assert res_nho["labor_cost_vnd"] > 0
    assert res_nho["equipment_cost_vnd"] > 0

    # 3. Đóng cọc tre (AC.11110)
    res_tre = BoqRateBreakdownEngine.breakdown_item_rate(
        item_name="Đóng cọc tre tươi L=2.5m d>=60-80mm gia cố nền móng",
        category="foundation",
        unit="cọc",
        total_unit_price=19500.0,
    )
    assert res_tre["norm_code"] == "AC.11110"
    mats_tre = res_tre["material_breakdown"]
    assert any(
        "COC-TRE" in m["material_code"] or "cọc tre" in m["material_name"].lower()
        for m in mats_tre
    )


def test_ai_quynh_system_prompts_grounded_in_thong_tu_38():
    """Kiểm tra System Prompt của AI Quỳnh đã được tích hợp bảng tra cứu định mức Thông tư 38/2026/TT-BXD."""
    vision_prompt = get_vision_system_prompt()
    assert "Thông tư 38/2026/TT-BXD" in vision_prompt
    assert "AC.22111" in vision_prompt
    assert "AC.22112" in vision_prompt
    assert "AC.11110" in vision_prompt
    assert "TUYỆT ĐỐI KHÔNG DÙNG MÃ AC.11110 CHO CỌC CỪ LARSEN" in vision_prompt

    training_prompt = build_quynh_system_prompt()
    assert "Thông tư 38/2026/TT-BXD" in training_prompt
    assert "AC.22111" in training_prompt


def test_ai_quynh_fallback_correction_learns_thong_tu_38_directive():
    """Kiểm tra phản hồi hiệu chỉnh của AI Quỳnh khi nhận chỉ đạo về cừ Larsen và Thông tư 38."""
    dummy_items = [
        {
            "id": "item-1",
            "item_order": 1,
            "wbs_code": "1.2",
            "norm_code": "AC.11110",  # Sai mã cũ
            "item_name": "Ép cọc cừ thép Larsen IV gia cố hố móng",
            "category": "foundation",
            "quantity": 3420.0,
            "unit_price_vnd": 125000.0,
            "unit": "md",
        }
    ]
    resp = build_quynh_fallback_response(
        user_message="AC.11110 là định mức cọc tre, cừ Larsen quy định tại Thông tư 38/2026/TT-BXD là AC.22111 và AC.22112",
        current_user_name="Kỹ Sư Trưởng",
        current_items=dummy_items,
        drawing_type="hydraulic_culvert",
    )
    assert "Thông tư số 38/2026/TT-BXD" in resp["reply_message"]
    assert "AC.22111" in resp["reply_message"]

    # Kiểm tra danh mục hiệu chỉnh đã được đổi sang AC.22111
    corrections = resp["suggested_corrections"]
    assert any(i.get("norm_code") == "AC.22111" for i in corrections)

    # Kiểm tra quy tắc rút kinh nghiệm
    rules = resp["extracted_rules"]
    assert len(rules) >= 1
    assert any(
        "38/2026/TT-BXD" in r["correction_rule"] or "AC.22111" in r["correction_rule"]
        for r in rules
    )


def test_api_chat_train_quynh_larsen_norm_correction():
    """Kiểm thử API chat huấn luyện AI Quỳnh tiếp thu quy tắc Thông tư 38/2026/TT-BXD và Rule 12 teardown."""
    client = TestClient(app)
    erp_client = ErpDatabaseClient()

    takeoff_id = str(uuid.uuid4())
    item_id = str(uuid.uuid4())

    try:
        erp_client.create_drawing_takeoff(
            {
                "id": takeoff_id,
                "drawing_code": "DWG-TEST-TT38",
                "drawing_title": "Bản vẽ Cống Kênh Thử Nghiệm",
                "drawing_type": "hydraulic_culvert",
                "total_estimated_cost_vnd": 50000000.0,
            }
        )
        erp_client.create_drawing_takeoff_item(
            {
                "id": item_id,
                "takeoff_id": takeoff_id,
                "item_order": 1,
                "wbs_code": "1.2",
                "norm_code": "AC.11110",
                "item_name": "Ép cọc cừ thép Larsen IV gia cố hố móng",
                "category": "foundation",
                "quantity": 3420.0,
                "unit_price_vnd": 125000.0,
                "unit": "md",
            }
        )

        # Gửi tin nhắn chỉ đạo sửa lỗi
        post_res = client.post(
            f"/v1/takeoff/{takeoff_id}/chat-train",
            headers=AUTH_HEADERS,
            json={
                "message": "Mã AC.11110 là cọc tre, cừ Larsen phải áp mã AC.22111 theo Thông tư 38/2026/TT-BXD",
                "auto_apply": True,
            },
        )
        assert post_res.status_code == 200
        data = post_res.json()
        assert data["status"] == "success"
        assert "reply_message" in data
        assert len(data["suggested_corrections"]) >= 1

        # Kiểm tra item đã được auto_apply đổi sang AC.22111
        items = erp_client.list_drawing_takeoff_items(takeoff_id)
        assert any(i["norm_code"] == "AC.22111" for i in items)

    finally:
        # Rule 12 Teardown
        with erp_client.get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    "DELETE FROM erp_drawing_takeoff_items WHERE takeoff_id = %s;",
                    (takeoff_id,),
                )
                cur.execute(
                    "DELETE FROM erp_ai_takeoff_chat_messages WHERE takeoff_id = %s;",
                    (takeoff_id,),
                )
                cur.execute(
                    "DELETE FROM erp_drawing_takeoffs WHERE id = %s;", (takeoff_id,)
                )
                cur.execute(
                    "DELETE FROM erp_ai_takeoff_learned_rules WHERE learned_from_user LIKE '%TEST%' OR error_pattern LIKE '%DWG-TEST-TT38%';"
                )
                conn.commit()
