"""Unit and integration tests for document taxonomy and auto-numbering {Số}/{Năm}/{Mã}-ĐS."""

from __future__ import annotations

import unittest
from datetime import datetime
from typing import Any

from fastapi.testclient import TestClient

from app.core.postgres.erp_client import ErpDatabaseClient
from app.main import create_app
from app.modules.auth.presentation.auth import get_current_user
from app.modules.core.domain.document_taxonomy import (
    DOCUMENT_GROUPS,
    DOCUMENT_TYPES,
    get_document_type,
    get_group_for_type,
    get_taxonomy_grouped,
)


class TestDocumentTaxonomyAndAutoNumber(unittest.TestCase):
    def setUp(self) -> None:
        self.erp_client = ErpDatabaseClient()
        self.created_doc_ids: list[str] = []

    def tearDown(self) -> None:
        with self.erp_client.get_connection() as conn:
            with conn.cursor() as cur:
                for doc_id in self.created_doc_ids:
                    try:
                        cur.execute(
                            "DELETE FROM erp_documents WHERE id = %s OR parent_document_id = %s OR root_document_id = %s;",
                            (doc_id, doc_id, doc_id),
                        )
                    except Exception:
                        pass
                conn.commit()

    def test_domain_taxonomy_hierarchy(self) -> None:
        """Kiểm tra cấu trúc 5 Đại nhóm nghiệp vụ và danh mục sub-types."""
        self.assertIn("legal", DOCUMENT_GROUPS)
        self.assertIn("contract", DOCUMENT_GROUPS)
        self.assertIn("technical", DOCUMENT_GROUPS)
        self.assertIn("site", DOCUMENT_GROUPS)
        self.assertIn("financial", DOCUMENT_GROUPS)
        self.assertIn("other", DOCUMENT_GROUPS)

        # Kiểm tra tra cứu loại
        tm = get_document_type("TM")
        self.assertIsNotNone(tm)
        self.assertEqual(tm["group"], "technical")
        self.assertEqual(tm["name"], "Thuyết minh & Dự toán sơ bộ")

        unc = get_document_type("UNC")
        self.assertIsNotNone(unc)
        self.assertEqual(unc["group"], "financial")

        # Kiểm tra nhóm cho các loại
        self.assertEqual(get_group_for_type("CV"), "legal")
        self.assertEqual(get_group_for_type("HĐ"), "contract")
        self.assertEqual(get_group_for_type("BV"), "technical")
        self.assertEqual(get_group_for_type("BBNT"), "site")
        self.assertEqual(get_group_for_type("SK"), "financial")
        self.assertEqual(get_group_for_type("UNKNOWN_CUSTOM"), "other")

        grouped = get_taxonomy_grouped()
        self.assertEqual(len(grouped), 6)
        self.assertTrue(len(grouped["technical"]["items"]) >= 4)

    def test_auto_numbering_suffix_ds(self) -> None:
        """Kiểm tra quy tắc sinh số hiệu tự động {Số}/{Năm}/{Mã}-ĐS."""
        current_year = datetime.now().year

        # 1. Kiểm tra loại CV
        res_cv = self.erp_client.get_next_document_code("CV")
        self.assertEqual(res_cv["doc_type"], "CV")
        self.assertEqual(res_cv["year"], current_year)
        self.assertTrue(res_cv["next_code"].endswith(f"/{current_year}/CV-ĐS"))

        # 2. Kiểm tra loại Thuyết minh (TM)
        res_tm = self.erp_client.get_next_document_code("TM")
        self.assertEqual(res_tm["doc_type"], "TM")
        self.assertTrue(res_tm["next_code"].endswith(f"/{current_year}/TM-ĐS"))

        # 3. Kiểm tra loại Tùy biến (Custom Suffix)
        res_custom = self.erp_client.get_next_document_code("HDNT")
        self.assertEqual(res_custom["doc_type"], "HDNT")
        self.assertTrue(res_custom["next_code"].endswith(f"/{current_year}/HDNT-ĐS"))

    def test_api_taxonomy_and_next_number_endpoints(self) -> None:
        """Kiểm tra các API endpoints /taxonomy và /next-number."""
        app = create_app()

        def override_auth() -> dict[str, Any]:
            return {"user_id": "test_auditor", "role": "superadmin", "email": "test@dscons.vn"}

        app.dependency_overrides[get_current_user] = override_auth
        client = TestClient(app)

        # GET /v1/erp/documents/taxonomy
        res_tax = client.get("/v1/erp/documents/taxonomy")
        self.assertEqual(res_tax.status_code, 200)
        data_tax = res_tax.json()
        self.assertIn("groups", data_tax)
        self.assertIn("types", data_tax)
        self.assertIn("hierarchy", data_tax)
        self.assertIn("technical", data_tax["hierarchy"])

        # GET /v1/erp/documents/next-number?doc_type=TM
        res_next = client.get("/v1/erp/documents/next-number?doc_type=TM")
        self.assertEqual(res_next.status_code, 200)
        data_next = res_next.json()
        self.assertEqual(data_next["doc_type"], "TM")
        self.assertTrue(data_next["next_code"].endswith("-ĐS"))

    def test_document_group_auto_resolve_and_filtering(self) -> None:
        """Tạo văn bản với document_type kỹ thuật và kiểm tra document_group được tự động gán."""
        with self.erp_client.get_connection() as conn, conn.cursor() as cur:
            cur.execute("SELECT id FROM companies LIMIT 1;")
            c_row = cur.fetchone()
            company_id = str(c_row["id"]) if c_row else None

        doc = self.erp_client.create_document({
            "company_id": company_id,
            "document_title": "Bản vẽ thiết kế thi công cống hộp mẫu kiểm thử",
            "document_type": "BV",
            "document_code": "AUTO-TEST-BV",
            "summary_content": "Kiểm thử phân loại tự động",
        })
        self.created_doc_ids.append(doc["id"])

        self.assertEqual(doc["document_type"], "BV")
        self.assertEqual(doc["document_group"], "technical")
        self.assertTrue(doc["document_code"].endswith("/BV-ĐS"))

        # Lọc danh sách theo document_group
        docs_tech = self.erp_client.list_documents(document_group="technical")
        found = any(d["id"] == doc["id"] for d in docs_tech)
        self.assertTrue(found, "Document should be found when filtering by document_group='technical'")
