"""Automated Regression Tests for AEC 3-Way Matching Engine (Hóa Đơn <-> Dự Án WBS <-> Giá Sở Xây Dựng Hải Phòng).
Strict Zero-Tolerance Synthetic Data & Regression Gate 100% COMPLIANT.
"""

import pytest
from fastapi.testclient import TestClient

from app.main import create_app
from app.modules.auth.application.auth_service import AuthService
from app.modules.invoices.application.aec_3way_matching_service import Aec3WayMatchingService


@pytest.fixture(scope="module")
def app_client():
    app = create_app()
    return TestClient(app)


@pytest.fixture(scope="module")
def auth_headers():
    auth = AuthService()
    token = auth.create_jwt_token({
        "id": "admin-id",
        "email": "director@dscons.vn",
        "role": "superadmin",
        "full_name": "Nguyễn Sĩ Sơn",
        "company_id": "0753d827-90e1-4894-9c16-266ca572c5eb",
    })
    return {"Authorization": f"Bearer {token}"}


def test_3way_matching_summary():
    """Kiểm thử tổng hợp KPI đối soát 3 chiều toàn hệ thống."""
    service = Aec3WayMatchingService()
    summary = service.get_matching_summary()

    assert summary["total_invoices"] >= 1000
    assert summary["total_amount_vnd"] > 40_000_000_000
    assert summary["matched_invoices"] > 0
    assert summary["unmatched_invoices"] > 0
    assert summary["price_benchmark"]["audited_items_count"] > 0


def test_3way_matching_list_and_filters():
    """Kiểm thử danh sách hóa đơn mua vào với bộ lọc."""
    service = Aec3WayMatchingService()
    res_all = service.list_matching_invoices(status="ALL", limit=10)
    assert res_all["total"] >= 1000
    assert len(res_all["invoices"]) == 10

    # Lọc chưa khớp
    res_unmatched = service.list_matching_invoices(status="UNMATCHED", limit=5)
    assert all(inv["matched_project_id"] is None for inv in res_unmatched["invoices"])


def test_3way_matching_dry_run():
    """Kiểm thử thuật toán AI quét tự động đối soát hàng loạt ở chế độ Dry-Run."""
    service = Aec3WayMatchingService()
    dry_res = service.batch_auto_match(dry_run=True, max_items=100)

    assert dry_res["dry_run"] is True
    assert dry_res["total_unmatched_scanned"] <= 100
    assert dry_res["matched_count"] > 0
    assert dry_res["matched_amount_vnd"] > 0
    assert 2 in dry_res["pillar_breakdown"]  # Trụ Cột 2 (Vận tải Howo / Dầu DO)


def test_3way_api_endpoints(app_client, auth_headers):
    """Kiểm thử các API routes 3-Way Matching và thẩm tra giá Sở Xây Dựng."""
    # 1. Summary API
    resp_sum = app_client.get("/v1/erp/invoices/3way-matching/summary", headers=auth_headers)
    assert resp_sum.status_code == 200
    data_sum = resp_sum.json()
    assert "total_invoices" in data_sum
    assert "price_benchmark" in data_sum

    # 2. List API
    resp_list = app_client.get("/v1/erp/invoices/3way-matching/list?status=ALL&limit=5", headers=auth_headers)
    assert resp_list.status_code == 200
    invoices = resp_list.json()["invoices"]
    assert len(invoices) == 5

    # 3. Detail API
    first_id = invoices[0]["id"]
    resp_det = app_client.get(f"/v1/erp/invoices/3way-matching/{first_id}/audit-detail", headers=auth_headers)
    assert resp_det.status_code == 200
    assert "invoice" in resp_det.json()
    assert "items" in resp_det.json()

    # 4. Batch dry-run API
    resp_batch = app_client.post(
        "/v1/erp/invoices/3way-matching/batch-auto-match",
        json={"dry_run": True, "max_items": 50},
        headers=auth_headers
    )
    assert resp_batch.status_code == 200
    assert resp_batch.json()["dry_run"] is True


def test_multi_project_allocation_lifecycle(app_client, auth_headers):
    """Kiểm thử toàn diện tính năng 1 hóa đơn nhập vật tư phân bổ cho nhiều dự án."""
    service = Aec3WayMatchingService()
    summary = service.get_matching_summary()
    assert summary["total_invoices"] > 0

    # Lấy 1 hóa đơn thực tế và 2 dự án thực tế
    with service.db.get_connection() as conn, conn.cursor() as cur:
        cur.execute("SELECT id FROM erp_invoices WHERE direction = 'input' LIMIT 1;")
        inv_id = str(cur.fetchone()["id"])
        cur.execute("SELECT id FROM projects ORDER BY project_code LIMIT 2;")
        p_rows = cur.fetchall()
        assert len(p_rows) >= 2
        p1_id, p2_id = str(p_rows[0]["id"]), str(p_rows[1]["id"])

    # 1. Gọi GET allocations
    resp_get = app_client.get(
        f"/v1/erp/invoices/3way-matching/{inv_id}/allocations",
        headers=auth_headers
    )
    assert resp_get.status_code == 200
    get_data = resp_get.json()
    assert "total_amount_vnd" in get_data
    assert "items" in get_data

    # 2. Gọi POST allocations phân bổ cho 2 công trình
    alloc_payload = {
        "allocations": [
            {
                "project_id": p1_id,
                "allocated_quantity": 10.0,
                "allocated_total_amount_vnd": 600000.0,
                "notes": "Phân bổ công trình 1"
            },
            {
                "project_id": p2_id,
                "allocated_quantity": 5.0,
                "allocated_total_amount_vnd": 400000.0,
                "notes": "Phân bổ công trình 2"
            }
        ]
    }
    resp_post = app_client.post(
        f"/v1/erp/invoices/3way-matching/{inv_id}/allocations",
        json=alloc_payload,
        headers=auth_headers
    )
    assert resp_post.status_code == 200
    post_res = resp_post.json()
    assert post_res["projects_count"] == 2
    assert post_res["total_allocated_vnd"] == 1000000.0

    # 3. Xác nhận lại qua GET allocations
    resp_verify = app_client.get(
        f"/v1/erp/invoices/3way-matching/{inv_id}/allocations",
        headers=auth_headers
    )
    assert resp_verify.status_code == 200
    verify_data = resp_verify.json()
    assert len(verify_data["allocations"]) == 2
    assert verify_data["total_allocated_vnd"] == 1000000.0

