"""
Poe2VisualTool Hardware Fingerprint (HWID) Engine
Sinh mã định danh phần cứng độc nhất (Deterministic Machine HWID).
Thu thập:
  - Motherboard UUID (CIM / Registry MachineGuid)
  - CPU Processor ID
  - Primary Disk Serial Number / Volume Serial
  - Salted SHA-256 Hash -> Định dạng thương mại: PVT-XXXX-XXXX-XXXX-XXXX
100% An toàn, không thay đổi sau khi khởi động lại máy.
Bản quyền 2026 Poe2VisualTool.
"""

from __future__ import annotations

import ctypes
import hashlib
import os
import platform
import subprocess
from typing import Dict, Optional

# Chuỗi muối bảo mật cho thuật toán băm HWID
HWID_SALT = "Poe2VisualTool-Commercial-HWID-Salt-2026-v1"


def _get_registry_machine_guid() -> str:
    """Lấy MachineGuid từ Windows Registry."""
    if os.name != "nt":
        return ""
    try:
        import winreg
        key = winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SOFTWARE\Microsoft\Cryptography",
            0,
            winreg.KEY_READ | winreg.KEY_WOW64_64KEY,
        )
        val, _ = winreg.QueryValueEx(key, "MachineGuid")
        winreg.CloseKey(key)
        return str(val).strip()
    except Exception:
        return ""


def _get_volume_serial() -> str:
    """Lấy số seri ổ đĩa hệ thống C:\\ qua GetVolumeInformationW."""
    if os.name != "nt":
        return ""
    try:
        serial = ctypes.c_ulong()
        ret = ctypes.windll.kernel32.GetVolumeInformationW(
            "C:\\", None, 0, ctypes.byref(serial), None, None, None, 0
        )
        if ret != 0:
            return f"{serial.value:08X}"
    except Exception:
        pass
    return ""


def _query_wmi_property(cim_class: str, prop: str) -> str:
    """Truy vấn thuộc tính phần cứng qua PowerShell Get-CimInstance (Nhanh & Hiện đại hơn wmic)."""
    if os.name != "nt":
        return ""
    try:
        cmd = [
            "powershell",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            f"(Get-CimInstance -ClassName {cim_class} -ErrorAction SilentlyContinue).{prop}",
        ]
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=3,
            creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
        )
        if result.returncode == 0:
            val = result.stdout.strip()
            if val and not val.lower().startswith("to be filled") and "none" not in val.lower():
                # Lấy dòng đầu tiên nếu có nhiều kết quả
                lines = [l.strip() for l in val.splitlines() if l.strip()]
                return lines[0] if lines else ""
    except Exception:
        pass
    return ""


_CACHED_DETAILS: Optional[Dict[str, str]] = None


def get_hardware_fingerprint_details() -> Dict[str, str]:
    """Thu thập các thông số phần cứng cốt lõi của máy tính (có đệm bộ nhớ cache)."""
    global _CACHED_DETAILS
    if _CACHED_DETAILS is not None:
        return _CACHED_DETAILS

    details: Dict[str, str] = {}

    # 1. Motherboard UUID
    mb_uuid = _query_wmi_property("Win32_ComputerSystemProduct", "UUID")
    if not mb_uuid or mb_uuid.lower() == "ffffffff-ffff-ffff-ffff-ffffffffffff":
        mb_uuid = _get_registry_machine_guid()
    details["motherboard_uuid"] = mb_uuid or "MB-DEFAULT-UUID"

    # 2. CPU Processor ID
    cpu_id = _query_wmi_property("Win32_Processor", "ProcessorId")
    if not cpu_id:
        cpu_id = platform.processor() or "CPU-DEFAULT-ID"
    details["cpu_id"] = cpu_id

    # 3. Disk Serial / Volume Serial
    disk_serial = _query_wmi_property("Win32_DiskDrive", "SerialNumber")
    if not disk_serial:
        disk_serial = _get_volume_serial() or "DISK-DEFAULT-SERIAL"
    details["disk_serial"] = disk_serial

    # 4. System MachineGuid (Backup cố định của bản cài đặt Windows)
    guid = _get_registry_machine_guid()
    if guid:
        details["machine_guid"] = guid

    _CACHED_DETAILS = details
    return details


def get_machine_hwid(custom_salt: Optional[str] = None) -> str:
    """
    Sinh mã băm HWID chuẩn hóa dành cho thương mại:
    Định dạng: PVT-XXXX-XXXX-XXXX-XXXX (16 ký tự hex chia thành 4 nhóm).
    Đảm bảo tính xác định (Deterministic): Cùng 1 máy luôn sinh cùng 1 mã.
    """
    salt = custom_salt or HWID_SALT
    details = get_hardware_fingerprint_details()

    # Xếp theo thứ tự cố định để bảo đảm tính tất định
    components = [
        details.get("motherboard_uuid", ""),
        details.get("cpu_id", ""),
        details.get("disk_serial", ""),
        details.get("machine_guid", ""),
        salt,
    ]
    raw_fingerprint = "|".join(c.strip().upper() for c in components)

    # Băm 2 vòng SHA-256 để chống brute-force
    first_pass = hashlib.sha256(raw_fingerprint.encode("utf-8")).digest()
    final_hash = hashlib.sha256(first_pass + salt.encode("utf-8")).hexdigest().upper()

    # Lấy 16 ký tự đầu để tạo mã HWID ngắn gọn, công thái học cho người dùng
    h = final_hash[:16]
    return f"PVT-{h[0:4]}-{h[4:8]}-{h[8:12]}-{h[12:16]}"
