from __future__ import annotations

import json
import logging
from typing import Any

import json_repair

logger = logging.getLogger("dscons.document_processing.analyzer")


class DocumentAnalyzerMixin:
    """LLM-based document analysis, metadata extraction, and version diffing."""

    async def analyze_with_ai(self, text: str, filename: str) -> dict[str, Any]:
        """Ask LLM to classify document group/type, stage, signature status, and extract fields as JSON."""
        from app.modules.agents.application.agent_security_guard import AgentSecurityGuard

        # 1. Zero-Trust Input Sanitization
        isolated_text, threats = AgentSecurityGuard.sanitize_untrusted_input(
            text[:6000]
        )

        system_prompt = (
            "Bạn là Chuyên viên Pháp lý & Hồ sơ Công trình (Persona Thảo) tại Công ty TNHH Xây Dựng Định Sơn.\n"
            "Nhiệm vụ của bạn là đọc kỹ văn bản công trình / thông báo mời thầu / quyết định / hợp đồng và trích xuất đầy đủ các trường thông tin vào đúng cấu trúc JSON sau:\n\n"
            "QUY TẮC BÓC TÁCH:\n"
            "1. document_code: Mã số văn bản, số quyết định hoặc Mã TBMT (ví dụ: 'IB2600471890', '87/QĐ-TTDVSNC', '12/2026/HĐ-ĐS', '01/2026/TM-ĐS'). Không để trống nếu văn bản có mã.\n"
            "2. document_title: Trích yếu nghiệp vụ đầy đủ (ví dụ: 'Thông báo mời thầu - Gói thầu số 05: Gói thầu xây lắp (Dự án Xây dựng cống hộp đoạn từ nhà ông Đèn đến nhà bà Lanh thôn Phong Cầu, xã Kiến Minh)').\n"
            "3. issuer_name: Tên đơn vị ban hành hoặc Chủ đầu tư (ví dụ: 'Trung tâm Dịch vụ sự nghiệp công xã Kiến Minh').\n"
            "4. partner_name: Tên đối tác hoặc Chủ đầu tư liên quan.\n"
            "5. issue_date: Ngày ban hành hoặc ngày đăng tải định dạng YYYY-MM-DD (ví dụ: '2026-08-22').\n"
            "6. summary_content: Tóm tắt 2-3 câu chi tiết về gói thầu/văn bản: tên dự án, thời gian thi công, giá trị bảo đảm, hình thức đấu thầu, thời điểm đóng/mở thầu.\n"
            "7. document_group: 'legal' (pháp lý, thông báo, tờ trình, quyết định) | 'contract' (hợp đồng, phụ lục, báo giá, hồ sơ thầu) | 'technical' (thuyết minh, bản vẽ, BPTC, chỉ dẫn) | 'site' (biên bản nghiệm thu, hiện trường, nhật ký, thí nghiệm) | 'financial' (ủy nhiệm chi, sao kê ngân hàng, giấy báo nợ/có, hóa đơn, thanh toán đợt IPC, quyết toán) | 'other'.\n"
            "8. document_type: Chọn mã ngắn chuẩn: 'CV' (Công văn), 'QĐ' (Quyết định), 'TB' (Thông báo), 'TTr' (Tờ trình), 'THU' (Thư từ), 'GUQ' (Giấy ủy quyền), 'HĐ' (Hợp đồng), 'PLHĐ' (Phụ lục HĐ), 'BG' (Báo giá/Chào giá), 'HSMT' (Hồ sơ mời thầu), 'HSDT' (Hồ sơ dự thầu), 'TM' (Thuyết minh/Dự toán sơ bộ), 'BV' (Bản vẽ kỹ thuật), 'BPTC' (Biện pháp thi công), 'CDKT' (Chỉ dẫn kỹ thuật), 'BB' (Biên bản), 'BBNT' (Nghiệm thu), 'NK' (Nhật ký), 'TN' (Thí nghiệm), 'KCS' (Kiểm tra vật tư), 'UNC' (Ủy nhiệm chi), 'SK' (Sao kê ngân hàng), 'GBN' (Giấy báo Nợ/Có), 'HDDT' (Hóa đơn), 'IPC' (Thanh toán đợt), 'QT' (Quyết toán), hoặc 'KHAC'.\n"
            "9. signature_status: 'fully_executed' (nếu là văn bản điện tử e-GP hoặc có chữ ký/con dấu) | 'signed_unsigned_seal' | 'draft'.\n"
            "10. TUYỆT ĐỐI KHÔNG tự chèn các từ khóa an toàn/bảo mật hệ thống (như 'bảo mật', 'an toàn', 'zero-trust', 'cảnh báo', 'untrusted') vào bất kỳ trường nào.\n\n"
            "Cấu trúc JSON bắt buộc:\n"
            "{\n"
            '  "document_code": "...",\n'
            '  "document_title": "...",\n'
            '  "document_group": "legal",\n'
            '  "document_type": "TB",\n'
            '  "signature_status": "fully_executed",\n'
            '  "document_direction": "incoming",\n'
            '  "project_stage": "stage_01_initiation",\n'
            '  "partner_name": "...",\n'
            '  "partner_tax_code": null,\n'
            '  "issuer_name": "...",\n'
            '  "signer_name": null,\n'
            '  "issue_date": "YYYY-MM-DD",\n'
            '  "summary_content": "...",\n'
            '  "ai_risk_assessment": "...",\n'
            '  "ai_legal_references": ["..."]\n'
            "}\n"
            "Lưu ý: Chỉ trả về chuỗi JSON thô bắt đầu bằng { và kết thúc bằng }."
        )

        user_content = f"Tên file gốc: {filename}\nNội dung văn bản:\n{isolated_text}"

        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_content},
        ]

        try:
            response_text = await self._llm_client.chat(messages, agent_code="thao")
            logger.info("Raw LLM Response: %s", response_text)

            # Sanitize response text
            cleaned_text = response_text.strip()
            cleaned_text = cleaned_text.removeprefix("```json")
            cleaned_text = cleaned_text.removeprefix("```")
            cleaned_text = cleaned_text.removesuffix("```")
            cleaned_text = cleaned_text.strip()

            # 2. Zero-Trust Output Data Loss Prevention (DLP)
            is_safe, dlp_text, dlp_flags = AgentSecurityGuard.inspect_output_dlp(
                cleaned_text
            )

            # Robust JSON extraction
            import re

            json_match = re.search(r"\{[\s\S]*\}", dlp_text)
            target_json_str = json_match.group(0) if json_match else dlp_text

            parsed = json_repair.repair_json(target_json_str, return_objects=True)
            if isinstance(parsed, dict):
                parsed["document_title"] = self.sanitize_document_title(
                    parsed.get("document_title"), filename
                )
                return parsed
            try:
                parsed_json = json.loads(target_json_str)
                if isinstance(parsed_json, dict):
                    parsed_json["document_title"] = self.sanitize_document_title(
                        parsed_json.get("document_title"), filename
                    )
                    return parsed_json
            except Exception:
                pass
        except Exception as e:
            logger.error("Failed to analyze document %s with LLM: %s", filename, e)

        # Fallback dictionary if LLM fails or output is not a dictionary
        fallback_title = self.sanitize_document_title(filename, filename)
        return {
            "document_group": "dispatch",
            "document_type": "CV",
            "signature_status": "draft",
            "document_direction": "incoming",
            "project_stage": "stage_01_initiation",
            "partner_name": None,
            "partner_tax_code": None,
            "document_code": None,
            "document_title": fallback_title,
            "issue_date": None,
            "issuer_name": None,
            "signer_name": None,
            "summary_content": "Không thể phân tích nội dung văn bản tự động bằng AI.",
            "ai_risk_assessment": "Lỗi phân tích cú pháp kết quả AI.",
            "ai_legal_references": [],
        }

    async def compare_document_versions(
        self, old_text: str, new_text: str, filename_old: str, filename_new: str
    ) -> dict[str, Any]:
        """Ask LLM to perform document diffing between two versions and highlight changes."""
        system_prompt = (
            "Bạn là chuyên gia thẩm định hồ sơ công trình và kiểm toán độc lập tại DSCons.\n"
            "Nhiệm vụ của bạn là so sánh 2 phiên bản văn bản (Bản cũ và Bản mới tải lên thay thế), phân tích các điểm sai khác, số liệu sửa đổi, bổ sung hoặc cắt giảm.\n"
            "Hãy trả về kết quả dưới định dạng JSON duy nhất:\n"
            "{\n"
            '  "summary_of_changes": "..." (Tóm tắt ngắn gọn các điểm sửa đổi cốt lõi, ví dụ: sửa lỗi chính tả, thay đổi đơn giá, tăng khối lượng, bổ sung người ký...),\n'
            '  "financial_impact": "..." (Đánh giá thay đổi về số tiền hoặc khối lượng nếu có, nếu không ghi rõ \'Không ảnh hưởng tài chính\'),\n'
            '  "legal_impact": "..." (Đánh giá hiệu lực pháp lý và rủi ro nếu có),\n'
            '  "key_differences": [\n'
            '     {"section": "...", "old_value": "...", "new_value": "...", "reason": "..."}\n'
            "  ]\n"
            "}\n"
            "Lưu ý: Chỉ trả về chuỗi JSON thô."
        )

        user_content = (
            f"--- BẢN CŨ ({filename_old}) ---\n{old_text[:3500]}\n\n"
            f"--- BẢN MỚI THAY THẾ ({filename_new}) ---\n{new_text[:3500]}\n"
        )

        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_content},
        ]

        try:
            response_text = await self._llm_client.chat(messages, agent_code="thao")
            cleaned_text = response_text.strip()
            cleaned_text = cleaned_text.removeprefix("```json")
            cleaned_text = cleaned_text.removeprefix("```")
            cleaned_text = cleaned_text.removesuffix("```")
            cleaned_text = cleaned_text.strip()

            parsed = json_repair.repair_json(cleaned_text, return_objects=True)
            if isinstance(parsed, dict):
                return parsed
        except Exception as e:
            logger.error("Failed to compare document versions with LLM: %s", e)

        return {
            "summary_of_changes": "Phiên bản mới được cập nhật thay thế cho bản cũ.",
            "financial_impact": "Không phát hiện thay đổi lớn về số liệu tài chính.",
            "legal_impact": "Cần kiểm tra đối soát chữ ký và con dấu pháp nhân.",
            "key_differences": [],
        }
