"""
Poe2VisualTool Commercial License Engine
Xác thực bản quyền mật mã học HMAC-SHA256, khóa máy theo HWID và quản lý thời hạn sử dụng.
Hỗ trợ:
  - Giấy phép Vĩnh viễn (LIFETIME)
  - Thuê bao theo thời hạn (SUBSCRIPTION 30d, 90d, 365d)
  - Chế độ dùng thử (TRIAL 24h / 3 ngày)
  - Định dạng Product Key chuẩn công nghiệp: PVTK-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
Bản quyền 2026 Poe2VisualTool.
"""

from __future__ import annotations

import base64
import hashlib
import hmac
import json
import os
import time
from dataclasses import dataclass
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path
from typing import Optional, Tuple

from src.commercial.hwid import get_machine_hwid

# Khóa bí mật ký số bản quyền thương mại (Master Commercial Secret)
# Trong môi trường sản xuất, khóa này được nhúng trong C++ core hoặc server
MASTER_LICENSE_SECRET = "Poe2VisualTool-2026-Commercial-Master-Secret-Ed4f81c9a0"

DEFAULT_TRIAL_DURATION_HOURS = 24


class LicenseTier(Enum):
    INVALID = "INVALID"
    TRIAL = "TRIAL"
    SUBSCRIPTION = "SUBSCRIPTION"
    LIFETIME = "LIFETIME"


@dataclass
class LicenseInfo:
    is_valid: bool
    tier: LicenseTier
    hwid: str
    issued_at: Optional[datetime]
    expires_at: Optional[datetime]
    days_left: int
    message: str
    raw_key: str = ""


class LicenseManager:
    """
    Trình quản lý giấy phép bản quyền phần mềm Poe2VisualTool.
    """

    def __init__(
        self,
        license_file_path: Optional[Path | str] = None,
        custom_hwid: Optional[str] = None,
        secret_key: Optional[str] = None,
    ):
        self.secret_key = secret_key or MASTER_LICENSE_SECRET
        self.hwid = custom_hwid or get_machine_hwid()

        if license_file_path:
            self.license_file = Path(license_file_path).resolve()
        else:
            # Ưu tiên lưu trong thư mục AppData của người dùng
            appdata = os.environ.get("APPDATA")
            if appdata:
                dir_path = Path(appdata) / "Poe2VisualTool"
            else:
                dir_path = Path(__file__).resolve().parents[2] / "config"
            self.license_file = dir_path / "license.dat"

    # --------------------------------------------------------------------------
    # THUẬT TOÁN KÝ VÀ GIẢI MÃ PRODUCT KEY
    # --------------------------------------------------------------------------

    @classmethod
    def generate_product_key(
        cls,
        target_hwid: str,
        tier: LicenseTier,
        duration_days: int = 0,
        secret_key: Optional[str] = None,
    ) -> str:
        """
        Sinh Product Key hợp lệ cho một máy đích (Dành cho Admin / Keygen).
        """
        secret = secret_key or MASTER_LICENSE_SECRET
        now = int(time.time())

        if tier == LicenseTier.LIFETIME:
            exp = 0
            tier_char = "L"
        elif tier == LicenseTier.TRIAL:
            exp = now + (duration_days if duration_days > 0 else 1) * 86400
            tier_char = "T"
        else:
            exp = now + max(1, duration_days) * 86400
            tier_char = "S"

        # Chuẩn hóa HWID loại bỏ tiền tố PVT- và gạch nối
        clean_hwid = target_hwid.replace("PVT-", "").replace("-", "").upper()
        if len(clean_hwid) < 16:
            clean_hwid = clean_hwid.ljust(16, "0")
        clean_hwid = clean_hwid[:16]

        # Payload: TIER (1 char) + EXPIRY_HEX (8 chars) + CLEAN_HWID (16 chars)
        exp_hex = f"{exp:08X}"
        body = f"{tier_char}{exp_hex}{clean_hwid}"

        # Chữ ký số HMAC-SHA256 rút gọn 10 ký tự
        sig = hmac.new(secret.encode("utf-8"), body.encode("utf-8"), hashlib.sha256).hexdigest().upper()[:10]

        # Full Raw Key: 35 ký tự
        raw_key = f"{body}{sig}"

        # Định dạng chuẩn: PVTK-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
        chunks = [raw_key[i : i + 5] for i in range(0, len(raw_key), 5)]
        return f"PVTK-{'-'.join(chunks)}"

    def verify_product_key(self, key_str: str) -> Tuple[bool, LicenseTier, int, str]:
        """
        Xác thực tính hợp lệ của Product Key đối với máy tính hiện tại.
        Trả về: (is_valid, tier, expires_at_timestamp, error_or_success_message)
        """
        if not key_str:
            return False, LicenseTier.INVALID, 0, "Chưa nhập mã bản quyền."

        cleaned = key_str.strip().upper().replace("PVTK-", "").replace("-", "")
        if len(cleaned) != 35:
            return False, LicenseTier.INVALID, 0, "Định dạng mã bản quyền không đúng độ dài."

        body = cleaned[:25]
        sig = cleaned[25:]

        tier_char = body[0]
        exp_hex = body[1:9]
        key_hwid = body[9:25]

        # 1. Kiểm tra chữ ký HMAC
        expected_sig = hmac.new(self.secret_key.encode("utf-8"), body.encode("utf-8"), hashlib.sha256).hexdigest().upper()[:10]
        if not hmac.compare_digest(sig, expected_sig):
            return False, LicenseTier.INVALID, 0, "Mã bản quyền không hợp lệ (Chữ ký không khớp)."

        # 2. Kiểm tra HWID máy tính
        my_clean_hwid = self.hwid.replace("PVT-", "").replace("-", "").upper()[:16]
        if key_hwid != my_clean_hwid:
            return False, LicenseTier.INVALID, 0, f"Mã bản quyền không dành cho máy tính này (HWID khác biệt)."

        # 3. Phân loại Tier & Kiểm tra thời hạn
        try:
            exp_timestamp = int(exp_hex, 16)
        except ValueError:
            return False, LicenseTier.INVALID, 0, "Mã bản quyền chứa thời hạn không hợp lệ."

        if tier_char == "L":
            tier = LicenseTier.LIFETIME
        elif tier_char == "T":
            tier = LicenseTier.TRIAL
        elif tier_char == "S":
            tier = LicenseTier.SUBSCRIPTION
        else:
            return False, LicenseTier.INVALID, 0, "Loại bản quyền không nhận diện được."

        now = int(time.time())
        if tier != LicenseTier.LIFETIME and exp_timestamp <= now:
            return False, tier, exp_timestamp, "Bản quyền đã hết hạn sử dụng."

        return True, tier, exp_timestamp, "Bản quyền hợp lệ và đã kích hoạt thành công!"

    # --------------------------------------------------------------------------
    # QUẢN LÝ TỆP BẢN QUYỀN (STORAGE & VALIDATION)
    # --------------------------------------------------------------------------

    def save_license(self, key_str: str) -> bool:
        """Lưu key bản quyền đã xác thực vào tệp license.dat."""
        valid, tier, exp, msg = self.verify_product_key(key_str)
        if not valid:
            return False

        try:
            self.license_file.parent.mkdir(parents=True, exist_ok=True)
            payload = {
                "key": key_str.strip().upper(),
                "hwid": self.hwid,
                "tier": tier.value,
                "expires_at": exp,
                "saved_at": int(time.time()),
            }
            raw_bytes = json.dumps(payload).encode("utf-8")
            obfuscated = base64.b64encode(raw_bytes).decode("ascii")
            self.license_file.write_text(obfuscated, encoding="utf-8")
            return True
        except Exception:
            return False

    def load_license(self) -> LicenseInfo:
        """Đọc và thẩm định trạng thái bản quyền hiện tại từ đĩa."""
        if not self.license_file.is_file():
            return LicenseInfo(
                is_valid=False,
                tier=LicenseTier.INVALID,
                hwid=self.hwid,
                issued_at=None,
                expires_at=None,
                days_left=0,
                message="Chưa kích hoạt bản quyền.",
            )

        try:
            content = self.license_file.read_text(encoding="utf-8").strip()
            decoded = base64.b64decode(content.encode("ascii")).decode("utf-8")
            data = json.loads(decoded)
            key_str = data.get("key", "")

            valid, tier, exp, msg = self.verify_product_key(key_str)
            if not valid:
                return LicenseInfo(
                    is_valid=False,
                    tier=tier,
                    hwid=self.hwid,
                    issued_at=None,
                    expires_at=datetime.fromtimestamp(exp, tz=timezone.utc) if exp > 0 else None,
                    days_left=0,
                    message=msg,
                    raw_key=key_str,
                )

            now = int(time.time())
            if tier == LicenseTier.LIFETIME:
                days_left = 99999
                exp_dt = None
            else:
                days_left = max(0, int((exp - now) / 86400))
                exp_dt = datetime.fromtimestamp(exp, tz=timezone.utc)

            issued_dt = datetime.fromtimestamp(data.get("saved_at", now), tz=timezone.utc)

            return LicenseInfo(
                is_valid=True,
                tier=tier,
                hwid=self.hwid,
                issued_at=issued_dt,
                expires_at=exp_dt,
                days_left=days_left,
                message=msg,
                raw_key=key_str,
            )
        except Exception as exc:
            return LicenseInfo(
                is_valid=False,
                tier=LicenseTier.INVALID,
                hwid=self.hwid,
                issued_at=None,
                expires_at=None,
                days_left=0,
                message=f"Tệp bản quyền bị lỗi hoặc chỉnh sửa bất hợp pháp: {exc}",
            )

    def activate_trial(self, hours: int = DEFAULT_TRIAL_DURATION_HOURS) -> bool:
        """Kích hoạt phiên bản Dùng Thử (Trial) tự động nếu chưa từng dùng thử."""
        trial_key = self.generate_product_key(
            target_hwid=self.hwid,
            tier=LicenseTier.TRIAL,
            duration_days=max(1, hours // 24),
            secret_key=self.secret_key,
        )
        return self.save_license(trial_key)
