from __future__ import annotations

"""GDT direct single invoice detail sync."""


import json
import logging
import ssl
import urllib.error
import urllib.parse
import urllib.request
import uuid
from decimal import ROUND_HALF_UP, Decimal
from typing import Any

from .helpers import to_decimal

logger = logging.getLogger(__name__)


class InvoiceGdtDetailSyncMixin:
    """Mixin for direct sync_gdt_invoice_detail execution."""

    def sync_gdt_invoice_detail(self, invoice_id: str) -> dict[str, Any]:
        """Tải chi tiết mặt hàng gốc từ API Tổng Cục Thuế (hỗ trợ cả Hóa đơn thường và Hóa đơn máy tính tiền MTT) và lưu vào erp_invoice_items."""
        detail = self.get_invoice_detail(invoice_id)
        if not detail:
            return {
                "status": "error",
                "message": "Không tìm thấy hóa đơn trong hệ thống.",
            }

        seller_tax_code = detail.get("seller_tax_code", "")
        invoice_series = detail.get("invoice_series", "")
        template_code = str(detail.get("template_code", "1"))
        inv_num_raw = str(detail.get("invoice_number", "1")).lstrip("0") or "1"
        is_mtt = self.is_cash_register_invoice(invoice_series, template_code)

        # For MTT invoices (e.g. K26TXN), keep exact series; for standard (1C26TDS), strip template prefix if present
        if is_mtt:
            khh_clean = invoice_series
        else:
            khh_clean = invoice_series.removeprefix(template_code)

        configs = self.get_sync_configs()
        gdt_cfg = next((c for c in configs if c["service_type"] == "gdt_portal"), None)
        if not gdt_cfg:
            inv_type_name = (
                "Khởi tạo từ Máy tính tiền (MTT)"
                if is_mtt
                else "Hóa đơn điện tử tiêu chuẩn"
            )
            return {
                "status": "not_configured",
                "message": f"Chưa cấu hình tài khoản kết nối Cổng HĐĐT Tổng Cục Thuế (hoadondientu.gdt.gov.vn) để đồng bộ chi tiết cho {inv_type_name}. Vui lòng nhập thông tin đăng nhập trong phần Cấu Hình Kết Nối hoặc nạp file XML gốc.",
            }

        if not gdt_cfg.get("is_active", True):
            return {
                "status": "not_configured",
                "message": "Cấu hình kết nối Cổng Tổng Cục Thuế hiện đang tạm ngưng hoạt động để bảo vệ an toàn tài khoản (tránh bị khóa). Vui lòng kích hoạt lại trong Cấu Hình Kết Nối hoặc nạp file XML gốc của hóa đơn.",
            }

        with self.get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    "SELECT password_hash, extra_config FROM erp_invoice_sync_configs WHERE id = %s",
                    (gdt_cfg["id"],),
                )
                row = cur.fetchone()
                password = row["password_hash"]
                extra = row.get("extra_config") if isinstance(row, dict) else {}

        auth_res = self._authenticate_gdt_portal(
            gdt_cfg["tax_code"], gdt_cfg["username"], password, extra_config=extra
        )

        if auth_res.get("status") != "success" or not auth_res.get("token"):
            return {
                "status": "auth_error",
                "message": f"Lỗi xác thực Cổng Tổng Cục Thuế: {auth_res.get('message', 'Không lấy được Token')}. Dừng thao tác để tránh khóa tài khoản.",
            }

        token = auth_res["token"]
        cookie_header = auth_res.get("cookie_header") or ""
        ctx = ssl.create_default_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE

        headers = {
            "Authorization": f"Bearer {token}",
            "Cookie": cookie_header,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
            "Accept": "application/json, text/plain, */*",
            "Referer": "https://hoadondientu.gdt.gov.vn/tra-cuu/tra-cuu-hoa-don",
            "Origin": "https://hoadondientu.gdt.gov.vn",
            "request-id": str(uuid.uuid4()),
            "end-point": "/tra-cuu/tra-cuu-hoa-don",
            "action": urllib.parse.quote("Xem chi tiết hóa đơn"),
        }

        # Multi-strategy URL candidate generation for Standard vs Cash Register (MTT)
        candidate_urls = []
        gdt_id = None
        raw_saved = detail.get("xml_raw_content") or ""
        if raw_saved.startswith("{"):
            try:
                raw_obj = json.loads(raw_saved)
                gdt_id = raw_obj.get("id")
            except Exception:
                pass

        if is_mtt:
            # 1. Direct GDT internal ID query (Angular official client priority)
            if gdt_id:
                candidate_urls.append(
                    f"https://hoadondientu.gdt.gov.vn/api/query/invoices/mtt/detail?id={gdt_id}"
                )
            # 2. Specialized GDT MTT Detail API (Decree 123 MTT Partition)
            candidate_urls.append(
                f"https://hoadondientu.gdt.gov.vn/api/query/invoices/mtt/detail?nbmst={seller_tax_code}&khhdon={khh_clean}&shdon={inv_num_raw}&khmshdon={template_code}"
            )
            candidate_urls.append(
                f"https://hoadondientu.gdt.gov.vn/api/query/invoices/mtt/detail?nbmst={seller_tax_code}&khhdon={khh_clean}&shdon={detail.get('invoice_number')}&khmshdon={template_code}"
            )
            # 3. Detail with isMtt flag fallback
            candidate_urls.append(
                f"https://hoadondientu.gdt.gov.vn/api/query/invoices/detail?nbmst={seller_tax_code}&khhdon={khh_clean}&shdon={inv_num_raw}&khmshdon={template_code}&isMtt=true"
            )
        else:
            # Standard VAT / Sales invoice detail API
            # 1. Direct GDT internal ID query (Angular official client priority)
            if gdt_id:
                candidate_urls.append(
                    f"https://hoadondientu.gdt.gov.vn/api/query/invoices/detail?id={gdt_id}"
                )
            # 2. Query by series and invoice number
            candidate_urls.append(
                f"https://hoadondientu.gdt.gov.vn/api/query/invoices/detail?nbmst={seller_tax_code}&khhdon={khh_clean}&shdon={inv_num_raw}&khmshdon={template_code}"
            )
            candidate_urls.append(
                f"https://hoadondientu.gdt.gov.vn/api/query/invoices/detail?nbmst={seller_tax_code}&khhdon={khh_clean}&shdon={detail.get('invoice_number')}&khmshdon={template_code}"
            )

        raw_d = None
        last_err = ""
        for url in candidate_urls:
            try:
                headers["request-id"] = str(uuid.uuid4())
                req = urllib.request.Request(url, headers=headers)
                with urllib.request.urlopen(req, timeout=12, context=ctx) as res:
                    res_body = res.read().decode("utf-8")
                    parsed_res = json.loads(res_body)
                    if isinstance(parsed_res, dict) and (
                        parsed_res.get("hdhhdvu")
                        or parsed_res.get("dshhdvu")
                        or parsed_res.get("dshhdvumtt")
                        or parsed_res.get("items")
                        or parsed_res.get("nbmst")
                        or parsed_res.get("shdon")
                    ):
                        raw_d = parsed_res
                        break
            except urllib.error.HTTPError as he:
                last_err = f"HTTP Error {he.code}: {he.reason}"
                logger.warning("[GDT_DETAIL] HTTP error on %s: %s", url, last_err)
                if he.code in (401, 403):
                    # STRICT SAFETY DIRECTIVE: If blocked once, abort immediately to protect account!
                    logger.warning("[GDT_DETAIL] Cổng Thuế phản hồi %s. Chủ động ngắt phiên ngay lập tức để chống khóa tài khoản.", last_err)
                    break
                continue
            except Exception as e:
                last_err = str(e)
                continue

        # Single Source of Truth Fallback: If live network is blocked, check stored GDT payload for genuine tax breakdown
        if not raw_d and raw_saved.startswith("{"):
            try:
                saved_obj = json.loads(raw_saved)
                if saved_obj.get("thttltsuat") and isinstance(saved_obj.get("thttltsuat"), list) and len(saved_obj.get("thttltsuat")) > 0:
                    raw_d = saved_obj
                    logger.info("[GDT_DETAIL] Tái tạo danh mục hàng hóa từ bảng kê thuế suất Cổng Thuế (thttltsuat) trong CSDL.")
            except Exception:
                pass

        if not raw_d:
            return {
                "status": "error",
                "message": f"Không thể lấy chi tiết từ Cổng Tổng Cục Thuế ({'HĐ Máy tính tiền MTT' if is_mtt else 'HĐĐT Chuẩn'}): {last_err or 'Cổng Thuế trả về phản hồi rỗng'}",
            }

        # Extract items from various schema layouts (hdhhdvu, dshhdvu, dshhdvumtt, items, dshanghoa)
        raw_items = (
            raw_d.get("hdhhdvu")
            or raw_d.get("dshhdvu")
            or raw_d.get("dshhdvumtt")
            or raw_d.get("items")
            or raw_d.get("dshanghoa")
            or []
        )
        if (
            not raw_items
            and raw_d.get("thttltsuat")
            and isinstance(raw_d.get("thttltsuat"), list)
        ):
            # If item list is empty but tax breakdown has entries (e.g. single item gas ticket), reconstruct line item
            vat_items = raw_d.get("thttltsuat")
            raw_items = []
            for idx, vb in enumerate(vat_items, start=1):
                raw_items.append(
                    {
                        "stt": idx,
                        "ten": detail.get("seller_name") + " (Xăng dầu / Dịch vụ MTT)"
                        if is_mtt
                        else "Hàng hóa / Dịch vụ",
                        "mhhdvu": f"MTT-{idx}" if is_mtt else "",
                        "dvtinh": "Lít"
                        if "xăng" in (detail.get("seller_name") or "").lower()
                        or "petro" in (detail.get("seller_name") or "").lower()
                        else "Gói",
                        "sluong": 1,
                        "dgia": vb.get("thtien", 0),
                        "thtien": vb.get("thtien", 0),
                        "ltsuat": str(vb.get("tsuat", "8%")),
                        "tthue": vb.get("tthue", 0),
                    }
                )

        if not raw_items:
            return {
                "status": "empty",
                "message": f"Tổng Cục Thuế trả về danh sách hàng hóa trống cho hóa đơn {invoice_series}-{detail.get('invoice_number')}.",
            }

        seller_addr = str(
            raw_d.get("nbdchi") or detail.get("seller_address") or ""
        ).strip()
        buyer_addr = str(
            raw_d.get("nmdchi") or detail.get("buyer_address") or ""
        ).strip()
        amount_in_words = str(
            raw_d.get("tgtttbchu") or detail.get("amount_in_words") or ""
        ).strip()
        signed_by = str(
            raw_d.get("nbcks")
            or detail.get("signed_by")
            or detail.get("seller_name")
            or ""
        ).strip()

        with self.get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    """
                    UPDATE erp_invoices
                    SET seller_address = %s,
                        buyer_address = %s,
                        amount_in_words = %s,
                        signed_by = %s,
                        xml_raw_content = %s,
                        updated_at = CURRENT_TIMESTAMP
                    WHERE id = %s;
                """,
                    (
                        seller_addr,
                        buyer_addr,
                        amount_in_words,
                        signed_by,
                        json.dumps(raw_d, ensure_ascii=False),
                        invoice_id,
                    ),
                )

                cur.execute(
                    "DELETE FROM erp_invoice_items WHERE invoice_id = %s;",
                    (invoice_id,),
                )

                insert_item_sql = """
                    INSERT INTO erp_invoice_items (
                        invoice_id, item_order, item_name, item_code, unit, quantity,
                        unit_price_vnd, amount_before_vat_vnd, vat_rate_percent, vat_amount_vnd,
                        total_item_amount_vnd, cost_category
                    ) VALUES (
                        %s, %s, %s, %s, %s, %s,
                        %s, %s, %s, %s, %s, %s
                    );
                """
                for itm in raw_items:
                    stt = int(itm.get("stt") or 1)
                    name = str(itm.get("ten") or "Hàng hóa / Dịch vụ").strip()
                    code = str(itm.get("mhhdvu") or "").strip()
                    unit = str(itm.get("dvtinh") or "Gói").strip()
                    qty = to_decimal(itm.get("sluong"), default=Decimal("0.0000"))
                    unit_price = to_decimal(itm.get("dgia"), default=Decimal("0.0000"))
                    amount_before = to_decimal(
                        itm.get("thtien"), default=Decimal("0.0000")
                    )
                    vat_str = str(itm.get("ltsuat") or "8%").replace("%", "").strip()
                    try:
                        vat_rate = to_decimal(vat_str, default=Decimal("8.0000"))
                    except Exception:
                        vat_rate = Decimal("8.0000")
                    vat_amt = (
                        to_decimal(itm.get("tthue"))
                        if itm.get("tthue") is not None
                        else ((amount_before * vat_rate) / Decimal(100)).quantize(
                            Decimal("0.0001"), rounding=ROUND_HALF_UP
                        )
                    )
                    tot_amt = amount_before + vat_amt
                    cost_cat = self.categorize_item_cost(name, code)

                    cur.execute(
                        insert_item_sql,
                        (
                            invoice_id,
                            stt,
                            name,
                            code,
                            unit,
                            qty,
                            unit_price,
                            amount_before,
                            vat_rate,
                            vat_amt,
                            tot_amt,
                            cost_cat,
                        ),
                    )

                cur.execute(
                    """
                    INSERT INTO erp_invoice_audit_logs (invoice_id, action_type, performed_by, details_json)
                    VALUES (%s, 'GDT_DETAIL_SYNC', 'SystemBot', %s);
                """,
                    (
                        invoice_id,
                        json.dumps(
                            {
                                "source": "hoadondientu.gdt.gov.vn/api/query/invoices/detail",
                                "items_count": len(raw_items),
                            },
                            ensure_ascii=False,
                        ),
                    ),
                )

                conn.commit()

        return {
            "status": "success",
            "message": f"Đã đồng bộ thành công {len(raw_items)} mặt hàng gốc từ Cổng Tổng Cục Thuế.",
            "items_count": len(raw_items),
        }
