"""
Offline trial license — auto-generates a 14-day trial on first launch.

No license server needed. The trial license is HMAC-signed locally and
works for 14 days. After expiry, the user must purchase a real license.

This is the key enabler for "users can try it right now."
"""
from __future__ import annotations

import hashlib
import hmac
import json
import os
import time
from datetime import datetime, timedelta, timezone
from pathlib import Path

from license_server.config import SIGNING_SECRET, PRODUCT_ID, LICENSE_VERSION, CLIENT_LICENSE_DIR, CLIENT_LICENSE_FILE

TRIAL_DAYS = int(os.environ.get("GAT_TRIAL_DAYS", "14"))
TRIAL_MAX_PER_HWID = int(os.environ.get("GAT_TRIAL_MAX_PER_HWID", "1"))  # 1 = one trial ever per machine
TRIAL_GRACE_DAYS = int(os.environ.get("GAT_TRIAL_GRACE_DAYS", "90"))    # must wait 90 days after expiry to re-trial
TRIAL_STATE_FILE = CLIENT_LICENSE_DIR / ".trial_claimed"

# Admin override: set this env var to a hardware ID to reset that machine's trial
ADMIN_RESET_HWID = os.environ.get("GAT_RESET_TRIAL_HWID", "")


def _sign(payload: dict) -> str:
    data = json.dumps(payload, sort_keys=True, ensure_ascii=False).encode()
    return hmac.new(SIGNING_SECRET.encode(), data, hashlib.sha256).hexdigest()


def can_claim_trial() -> bool:
    """Check if trial is still available (not yet claimed and not expired)."""
    from src.license.validator import _get_hardware_id
    current_hwid = _get_hardware_id()

    # Admin override: reset trial for a specific hardware ID
    if ADMIN_RESET_HWID and current_hwid == ADMIN_RESET_HWID:
        if TRIAL_STATE_FILE.exists():
            TRIAL_STATE_FILE.unlink()
        return True

    # Track ALL trial claims on this machine
    history = _load_trial_history()

    if not history:
        return True  # First time ever

    # Check hard limit: max N trials per hardware ID
    if len(history) >= TRIAL_MAX_PER_HWID:
        return False

    # Check grace period: must wait after last trial expired
    last_trial = history[-1]
    claimed_at = last_trial.get("claimed_at", "")
    if claimed_at:
        claimed_dt = datetime.fromisoformat(claimed_at)
        if datetime.now(timezone.utc) < claimed_dt + timedelta(days=TRIAL_DAYS + TRIAL_GRACE_DAYS):
            return False  # Still within trial + grace period

    return True


def _load_trial_history() -> list[dict]:
    """Load trial claim history. Returns list of past claims."""
    if not TRIAL_STATE_FILE.exists():
        return []
    try:
        data = json.loads(TRIAL_STATE_FILE.read_text(encoding="utf-8"))
        claims = data.get("claims", [])
        if isinstance(claims, list):
            return claims
    except Exception:
        pass
    return []


def claim_trial() -> dict:
    """
    Generate and save a 14-day trial license.

    Returns {"ok": True, "license": {...}} or {"ok": False, "error": "..."}
    """
    if not can_claim_trial():
        return {"ok": False, "error": "TRIAL_ALREADY_CLAIMED",
                "message": "You have already used your free trial. Please purchase a license."}

    now = datetime.now(timezone.utc)
    expires = now + timedelta(days=TRIAL_DAYS)

    from src.license.validator import _get_hardware_id
    hwid = _get_hardware_id()

    payload = {
        "product": PRODUCT_ID,
        "version": LICENSE_VERSION,
        "tier": "trial",
        "customer_email": "",
        "issued_at": now.isoformat(),
        "expires_at": expires.isoformat(),
        "features": ["basic"],
        "hardware_id": hwid,
        "activated_at": now.isoformat(),
        "is_trial": True,
    }

    signature = _sign(payload)
    signed = {"payload": payload, "signature": signature}

    # Save license file
    CLIENT_LICENSE_DIR.mkdir(parents=True, exist_ok=True)
    CLIENT_LICENSE_FILE.write_text(
        json.dumps({"signed_license": signed}, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    os.chmod(CLIENT_LICENSE_FILE, 0o600)

    # Record trial claim
    TRIAL_STATE_FILE.write_text(json.dumps({
        "claimed_at": now.isoformat(),
        "hardware_id": hwid,
        "trial_days": TRIAL_DAYS,
    }, ensure_ascii=False, indent=2), encoding="utf-8")
    os.chmod(TRIAL_STATE_FILE, 0o600)

    days_left = TRIAL_DAYS
    return {
        "ok": True,
        "tier": "trial",
        "expires": expires.strftime("%Y-%m-%d"),
        "days_left": days_left,
        "features": ["basic"],
    }


def get_trial_status() -> dict:
    """Get current trial status for display."""
    lic_file = CLIENT_LICENSE_FILE
    if not lic_file.exists():
        return {"status": "NO_TRIAL", "can_claim": can_claim_trial()}

    try:
        raw = json.loads(lic_file.read_text(encoding="utf-8"))
        payload = raw.get("signed_license", {}).get("payload", {})
        if not payload.get("is_trial"):
            return {"status": "PAID_LICENSE", "tier": payload.get("tier", "pro")}

        expires_at = payload.get("expires_at", "")
        if expires_at:
            exp = datetime.fromisoformat(expires_at)
            now = datetime.now(timezone.utc)
            days_left = max(0, (exp - now).days)
            if now > exp:
                return {"status": "TRIAL_EXPIRED", "days_left": 0, "expired_at": expires_at}
            return {"status": "TRIAL_ACTIVE", "days_left": days_left, "expires": expires_at[:10]}
    except Exception:
        pass

    return {"status": "NO_TRIAL", "can_claim": can_claim_trial()}
