from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from license_client import LicenseClient
from customer_registration import (
    CustomerRegistrationInput,
    CustomerRegistrationResult,
    register_customer_once,
)

APP_ID = "INIContract"
KEY_FILE = Path.home() / "AppData" / "Roaming" / "PhanMemHopDong" / "license.key"

STATUS_MESSAGES = {
    0: "Hợp lệ",
    1: "Không hợp lệ hoặc bị khóa",
    2: "Đã hết hạn",
    3: "Vượt giới hạn thiết bị",
    4: "Offline quá ngưỡng cho phép",
}

PLAN_LABELS = {
    "free": "FREE",
    "trial": "TRIAL (30 ngày)",
    "starter": "STARTER",
    "pro": "PRO",
    "office": "OFFICE",
    "trial_30_days": "TRIAL (30 ngày)",
    "starter_30_days": "STARTER (30 ngày)",
    "starter_60_days": "STARTER (60 ngày)",
    "starter_90_days": "STARTER (90 ngày)",
    "starter_180_days": "STARTER (180 ngày)",
    "starter_1_year": "STARTER (1 năm)",
    "starter_lifetime": "STARTER Lifetime",
    "pro_30_days": "PRO (30 ngày)",
    "pro_60_days": "PRO (60 ngày)",
    "pro_90_days": "PRO (90 ngày)",
    "pro_180_days": "PRO (180 ngày)",
    "pro_1_year": "PRO (1 năm)",
    "pro_lifetime": "PRO Lifetime",
    "office_30_days": "OFFICE (30 ngày)",
    "office_60_days": "OFFICE (60 ngày)",
    "office_90_days": "OFFICE (90 ngày)",
    "office_180_days": "OFFICE (180 ngày)",
    "office_365_days": "OFFICE (1 năm)",
    "office_1_year": "OFFICE (1 năm)",
    "office_lifetime": "OFFICE Lifetime",
    "3_months": "STARTER Legacy (3 tháng)",
    "6_months": "STARTER Legacy (6 tháng)",
    "1_year": "PRO Legacy (1 năm)",
    "lifetime": "OFFICE Legacy (Trọn đời)",
}

NON_EXPIRING_PLANS = {"free", "starter_lifetime", "pro_lifetime", "office_lifetime", "lifetime"}

# Ánh xạ plan_id → tier
PLAN_TIER = {
    "free": "free",
    "trial": "trial",
    "starter": "starter",
    "pro": "pro",
    "office": "office",
    "trial_30_days": "trial",
    "starter_30_days": "starter", "starter_60_days": "starter",
    "starter_90_days": "starter", "starter_180_days": "starter",
    "starter_1_year": "starter", "starter_lifetime": "starter",
    "3_months": "starter", "6_months": "starter",
    "pro_30_days": "pro", "pro_60_days": "pro",
    "pro_90_days": "pro", "pro_180_days": "pro",
    "pro_1_year": "pro", "pro_lifetime": "pro", "1_year": "pro",
    "office_30_days": "office", "office_60_days": "office",
    "office_90_days": "office", "office_180_days": "office",
    "office_365_days": "office", "office_1_year": "office",
    "office_lifetime": "office", "lifetime": "office",
}

# Giới hạn theo tier — khớp bảng bang_gia.md
# -1 = không giới hạn
TIER_LIMITS: dict[str, dict] = {
    "free": {
        "price_monthly": 0,
        "max_contracts": 10,
        "max_templates": 2,
        "max_devices": 1,
        "has_digital_sign": True,
        "has_report": False,
        "has_backup_sync": False,
        "has_basic_permissions": False,
        "has_advanced_permissions": False,
        "has_advanced_report": False,
        "has_email_sync": False,
        "has_pdf_package": False,
        "has_audit_trail": False,
        "has_api_access": False,
        "has_sub_account": False,
        "has_industry_templates": False,
        "multi_mst": 1,
        "support": None,
    },
    "trial": {
        "price_monthly": 0,
        "max_contracts": 200,
        "max_templates": -1,
        "max_devices": 3,
        "has_digital_sign": True,
        "has_report": True,
        "has_backup_sync": True,
        "has_basic_permissions": True,
        "has_advanced_permissions": True,
        "has_advanced_report": True,
        "has_email_sync": True,
        "has_pdf_package": True,
        "has_audit_trail": True,
        "has_api_access": False,
        "has_sub_account": False,
        "has_industry_templates": False,
        "multi_mst": 1,
        "support": None,
    },
    "starter": {
        "price_monthly": 49_000,
        "max_contracts": 500,
        "max_templates": -1,
        "max_devices": 3,
        "has_digital_sign": True,
        "has_report": True,
        "has_backup_sync": True,
        "has_basic_permissions": True,
        "has_advanced_permissions": False,
        "has_advanced_report": False,
        "has_email_sync": False,
        "has_pdf_package": False,
        "has_audit_trail": False,
        "has_api_access": False,
        "has_sub_account": False,
        "has_industry_templates": False,
        "multi_mst": 1,
        "support": "Email+Chat",
    },
    "pro": {
        "price_monthly": 99_000,
        "max_contracts": 1500,
        "max_templates": -1,
        "max_devices": 5,
        "has_digital_sign": True,
        "has_report": True,
        "has_backup_sync": True,
        "has_basic_permissions": True,
        "has_advanced_permissions": True,
        "has_advanced_report": True,
        "has_email_sync": True,
        "has_pdf_package": True,
        "has_audit_trail": True,
        "has_api_access": False,
        "has_sub_account": False,
        "has_industry_templates": False,
        "multi_mst": 2,
        "support": "Email+Chat",
    },
    "office": {
        "price_monthly": 199_000,
        "max_contracts": 5000,
        "max_templates": -1,
        "max_devices": -1,
        "has_digital_sign": True,
        "has_report": True,
        "has_backup_sync": True,
        "has_basic_permissions": True,
        "has_advanced_permissions": True,
        "has_advanced_report": True,
        "has_email_sync": True,
        "has_pdf_package": True,
        "has_audit_trail": True,
        "has_api_access": True,
        "has_sub_account": True,
        "has_industry_templates": True,
        "multi_mst": 5,
        "support": "SLA <4h + onboarding",
    },
}


def get_plan_family(plan_id: str | None) -> str:
    plan = (plan_id or "").strip().lower()
    if not plan:
        return "free"
    if plan in PLAN_TIER:
        return PLAN_TIER[plan]
    if plan.startswith("trial"):
        return "trial"
    if plan.startswith("starter_"):
        return "starter"
    if plan.startswith("pro_"):
        return "pro"
    if plan.startswith("office_"):
        return "office"
    return "free"


def get_plan_limits(plan_id: str) -> dict:
    """Trả về dict giới hạn tính năng cho plan_id đã cho."""
    tier = get_plan_family(plan_id)
    return TIER_LIMITS[tier]


@dataclass
class ActivationResult:
    ok: bool
    status: int
    status_message: str
    plan_id: str
    plan_label: str
    plan_tier: str
    limits: dict
    days_remaining: int
    show_days_remaining: bool
    days_remaining_text: str
    runtime_key: int
    client: LicenseClient

    def has_feature(self, feature_name: str) -> bool:
        return bool(self.limits.get(feature_name, False))

    def can_use_devices(self, current_devices: int) -> bool:
        max_devices = int(self.limits.get("max_devices", -1))
        return max_devices < 0 or current_devices <= max_devices

    def can_create_contracts(self, current_contracts: int) -> bool:
        max_contracts = int(self.limits.get("max_contracts", -1))
        return max_contracts < 0 or current_contracts < max_contracts


def _ensure_parent_dir(path: Path) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)


def load_license_key() -> str:
    if KEY_FILE.exists():
        return KEY_FILE.read_text(encoding="utf-8").strip()
    return ""


def save_license_key(key: str) -> None:
    _ensure_parent_dir(KEY_FILE)
    KEY_FILE.write_text(key.strip(), encoding="utf-8")


def activate_license(input_key: str | None = None, app_id: str = APP_ID) -> ActivationResult:
    client = LicenseClient(app_id)
    license_key = (input_key or load_license_key()).strip()

    if not license_key:
        raise RuntimeError("Chưa có license.key. Hãy nhập key và gọi lại.")

    runtime_key = client.activate(license_key)
    status = client.status
    plan_id = client.plan
    raw_days = client.days_remaining

    # Mọi gói hết hạn -> tự động xuống free (không báo expired)
    if status == 2:
        status = 0
        plan_id = "free"
        raw_days = 0

    show_days = plan_id not in NON_EXPIRING_PLANS
    days_text = f"{max(raw_days, 0)} ngày" if show_days else ""

    if status == 0:
        save_license_key(license_key)

    plan_tier = get_plan_family(plan_id)
    limits = get_plan_limits(plan_id)

    return ActivationResult(
        ok=(status == 0),
        status=status,
        status_message=STATUS_MESSAGES.get(status, f"Status không xác định: {status}"),
        plan_id=plan_id,
        plan_label=PLAN_LABELS.get(plan_id, plan_id),
        plan_tier=plan_tier,
        limits=limits,
        days_remaining=raw_days,
        show_days_remaining=show_days,
        days_remaining_text=days_text,
        runtime_key=runtime_key,
        client=client,
    )


def activate_or_raise(input_key: str | None = None, app_id: str = APP_ID) -> ActivationResult:
    result = activate_license(input_key=input_key, app_id=app_id)
    if not result.ok:
        raise RuntimeError(
            f"License không hợp lệ. status={result.status}, message={result.status_message}, plan={result.plan_id}"
        )
    return result


def register_customer_once_or_raise(data: CustomerRegistrationInput) -> CustomerRegistrationResult:
    result = register_customer_once(data)
    if not result.ok:
        raise RuntimeError(result.message)
    return result
