"""Unit & Integration Tests for Vietnamese CAD Font Transcoder & AutoCAD DWG/DXF Processing.
Specialists: Quynh (QS & BoQ Takeoff), Hung (Site Engineering), Minh (System Standards).
"""

from __future__ import annotations

import asyncio
from pathlib import Path

import ezdxf
from fastapi.testclient import TestClient

from app.main import create_app
from app.modules.takeoff.application.drawing_takeoff_service import get_drawing_takeoff_service
from app.modules.takeoff.application.vietnamese_cad_font_transcoder import (
    get_cad_font_transcoder,
)

client = TestClient(create_app())
AUTH_HEADERS = {"Authorization": "Bearer dev-test-token"}


def test_transcode_tcvn3_to_unicode():
    """Test converting legacy TCVN3 (ABC/.VnTime) encoded CAD strings to standard UTF-8 Unicode."""
    transcoder = get_cad_font_transcoder()

    # Sample 1: Construction concrete and rebar materials in standard TCVN3 bytes
    raw_tcvn1 = "B\xaa t\xabng m\xe3ng M300 \xae\xb8 1x2, c\xe8t th\xd0p CB300-V"
    expected1 = "Bê tông móng M300 đá 1x2, cốt thép CB300-V"
    assert transcoder.transcode_tcvn3_to_unicode(raw_tcvn1) == expected1

    # Sample 2: Irrigation project titles in standard TCVN3 bytes
    raw_tcvn2 = "C\xe8ng B\xd5n Kem - K\xcc \xa7a \xa7\xe9"
    expected2 = "Cống Bến Kem - Kè Đa Độ"
    assert transcoder.transcode_tcvn3_to_unicode(raw_tcvn2) == expected2

    # Sample 3: Concrete footing in standard TCVN3
    raw_tcvn3 = "B\xaa t\xabng l\xe3t m\xe3ng M100 d\xb5y 10cm"
    expected3 = "Bê tông lót móng M100 dày 10cm"
    assert transcoder.transcode_tcvn3_to_unicode(raw_tcvn3) == expected3


def test_transcode_vni_to_unicode():
    """Test converting legacy VNI-Windows encoded CAD strings to standard UTF-8 Unicode."""
    transcoder = get_cad_font_transcoder()

    # Sample 1: VNI concrete & materials
    raw_vni1 = "Beâ toâng moùng M300 ñaù 1x2, coát theùp"
    expected1 = "Bê tông móng M300 đá 1x2, cốt thép"
    assert transcoder.transcode_vni_to_unicode(raw_vni1) == expected1

    # Sample 2: VNI hydraulic structure title
    raw_vni2 = "Coáng Beán Kem - Keø Ña Ñoä"
    expected2 = "Cống Bến Kem - Kè Đa Độ"
    assert transcoder.transcode_vni_to_unicode(raw_vni2) == expected2


def test_clean_autocad_mtext():
    """Test cleaning AutoCAD MText escape sequences, formatting codes, and symbols."""
    transcoder = get_cad_font_transcoder()

    # Sample with \U+ hex, formatting block \f.VnTime, \P newline, and %%c diameter
    raw_mtext = r"\A1;{\f.VnTime|b0|i0;K\U+00E8 \U+0110a \U+0110\U+1ED9 - C\U+1ed1ng B\U+1ebfn Kem\P%%c18a200 d\U+00E0i 25.0m}"
    cleaned = transcoder.clean_autocad_mtext(raw_mtext)

    assert "Kè Đa Độ - Cống Bến Kem" in cleaned
    assert "Ø18a200" in cleaned
    assert "25.0m" in cleaned
    assert r"\A1;" not in cleaned
    assert r"\f.VnTime" not in cleaned


def test_auto_transcode_cad_text():
    """Test automatic font detection and transcoding."""
    transcoder = get_cad_font_transcoder()

    # Auto TCVN3
    res1 = transcoder.auto_transcode_cad_text(
        "B\xaa t\xabng l\xe3t m\xe3ng M100 d\xb5y 10cm"
    )
    assert res1 == "Bê tông lót móng M100 dày 10cm"

    # Auto VNI
    res2 = transcoder.auto_transcode_cad_text("Vaùn khuoân theùp ñònh hショnh")
    assert "Ván khuôn thép" in res2

    # Auto AutoCAD escape symbol
    res3 = transcoder.auto_transcode_cad_text(
        r"%%c20a150; Cao \U+0111\U+1ED9 \P%%p0.00m; G\U+00F3c nghi\U+00EAng 45%%d"
    )
    assert "Ø20a150" in res3
    assert "Cao độ" in res3
    assert "±0.00m" in res3
    assert "45°" in res3


def create_sample_dxf_drawing(
    tmp_path: Path, filename: str = "SAMPLE_CAD_AUTOCAD.dxf"
) -> Path:
    """Helper to generate a real AutoCAD DXF drawing with legacy Vietnamese font entities."""
    dxf_path = tmp_path / filename
    doc = ezdxf.new("R2018")
    msp = doc.modelspace()

    # Add foundation boundary polylines
    msp.add_lwpolyline([(0, 0), (25000, 0), (25000, 6500), (0, 6500)], close=True)

    # Add legacy TCVN3 text entities (.VnTime)
    msp.add_text(
        "C\xabng ty TNHH X\xa9y d\xf9ng \xa7\xdenh S\xacn - DSCons",
        dxfattribs={"height": 300},
    ).set_placement((500, 7000))
    msp.add_text(
        "B\xb6n v\xcf chi ti\xd5t: C\xe8ng B\xd5n Kem - K\xcc \xa7a \xa7\xe9",
        dxfattribs={"height": 400},
    ).set_placement((500, 6000))
    msp.add_text(
        "B\xaa t\xabng th\xa9n c\xe8ng M300 \xae\xb8 1x2", dxfattribs={"height": 250}
    ).set_placement((500, 5000))

    # Add AutoCAD MText entity with escape sequence and diameter symbol
    msp.add_mtext(
        r"{\fArial;C\U+1ed1t th\U+00e9p CB300-V: %%c18a200\PV\U+00e1n khu\U+00f4n th\U+00e9p \U+0111\U+1ecbnh h\U+00ecnh}",
        dxfattribs={"char_height": 250},
    )

    doc.saveas(str(dxf_path))
    return dxf_path


def test_dxf_file_takeoff_processing(tmp_path: Path):
    """Test end-to-end processing of AutoCAD DXF file with Vietnamese font normalization."""
    dxf_file = create_sample_dxf_drawing(tmp_path)
    service = get_drawing_takeoff_service()

    # 1. Test DXF rendering and text extraction
    rendered = service.render_dxf_to_images(dxf_file, dpi=100)
    assert len(rendered) >= 1
    assert len(rendered[0]["image_base64"]) > 100
    text_layer = rendered[0]["text_layer"]
    assert "Định Sơn" in text_layer
    assert "Cống Bến Kem" in text_layer or "Kè Đa Độ" in text_layer
    assert "Bê tông thân cống M300" in text_layer
    assert "Ø18a200" in text_layer

    # 2. Test full takeoff pipeline
    result = asyncio.run(
        service.process_drawing_file(
            file_path=dxf_file,
            filename="SAMPLE_CAD_AUTOCAD.dxf",
            drawing_hint="Bản vẽ AutoCAD cống hộp thủy lợi font TCVN3",
        )
    )

    assert result["status"] == "success"
    assert result["takeoff"]["id"] is not None
    assert len(result["items"]) >= 4
    assert result["metrics"]["total_estimated_cost_vnd"] > 0


def test_dxf_api_upload_flow(tmp_path: Path):
    """Test REST API upload endpoint with .dxf file."""
    dxf_file = create_sample_dxf_drawing(tmp_path, "API_CAD_UPLOAD.dxf")

    with open(dxf_file, "rb") as f:
        resp = client.post(
            "/v1/takeoff/upload-and-analyze",
            files={"file": ("API_CAD_UPLOAD.dxf", f, "application/dxf")},
            data={"drawing_hint": "Bản vẽ AutoCAD kiểm thử API upload"},
            headers=AUTH_HEADERS,
        )

    assert resp.status_code == 201, resp.text
    data = resp.json()
    assert data["status"] == "success"
    assert data["takeoff"]["drawing_code"] is not None
    assert len(data["items"]) >= 1
