"""
license_client.py
------------------
Drop-in license/HWID check for your own Termux/Android Python tool.
Talks to your self-hosted PHP + MySQL license API (see ../api and
../schema.sql) instead of a public Firebase database.

Usage in your main script:

    from license_client import check_license, calculate_time_left

    result = check_license()
    if not result:
        sys.exit()
    user_name, user_key, expiry = result
    print(f"Welcome {user_name} — {calculate_time_left(expiry)}")
"""

import os
import sys
import time
import random
import string
import platform
from datetime import datetime

import requests

# --- Configure these for your deployment ---
API_BASE_URL = "https://yourdomain.com/api"      # no trailing slash
API_SECRET = "CHANGE_THIS_TO_MATCH_config.php"   # must match config.php API_SECRET
APP_VERSION = "1.0"
# --------------------------------------------

SAVED_KEY_FILES = [
    "/sdcard/.mytool_device.id",
    os.path.expanduser("~/.mytool_key.txt"),
]

HEADERS = {"X-Api-Secret": API_SECRET, "Content-Type": "application/json"}


def _api_post(path, payload, timeout=10):
    try:
        res = requests.post(f"{API_BASE_URL}/{path}", json=payload, headers=HEADERS, timeout=timeout)
        return res.json()
    except Exception:
        return None


def _api_get(path, timeout=10):
    try:
        res = requests.get(f"{API_BASE_URL}/{path}", headers=HEADERS, timeout=timeout)
        return res.json()
    except Exception:
        return None


def get_device_model():
    try:
        brand = os.popen("getprop ro.product.brand").read().strip().capitalize()
        model = os.popen("getprop ro.product.model").read().strip()
        if brand and model:
            return model if brand.lower() in model.lower() else f"{brand} {model}"
        return model or brand or "Unknown Device"
    except Exception:
        return "Unknown Device"


def get_android_version():
    try:
        return os.popen("getprop ro.build.version.release").read().strip() or "Unknown"
    except Exception:
        return "Unknown"


def get_hwid():
    """Builds a stable per-device ID. Falls back to a random ID if nothing is available."""
    try:
        android_id = os.popen("settings get secure android_id").read().strip()
        serial = os.popen("getprop ro.serialno").read().strip()
        board = os.popen("getprop ro.board.platform").read().strip()
        device = os.popen("getprop ro.product.device").read().strip()
        combined = f"{android_id}_{serial}_{board}_{device}"
        if android_id and android_id not in ("null", "") and len(combined) > 10:
            return combined
    except Exception:
        pass
    try:
        brand = os.popen("getprop ro.product.brand").read().strip()
        model = os.popen("getprop ro.product.model").read().strip()
        if brand or model:
            return f"{brand}_{model}_{platform.node()}"
    except Exception:
        pass
    return "DEVICE_" + "".join(random.choices(string.ascii_uppercase + string.digits, k=8))


def calculate_time_left(expiry_str):
    if not expiry_str:
        return "Lifetime Access"
    try:
        fmt = "%Y-%m-%d %H:%M:%S" if len(expiry_str) > 10 else "%Y-%m-%d"
        exp_dt = datetime.strptime(expiry_str, fmt)
        diff = (exp_dt - datetime.now()).total_seconds()
        if diff <= 0:
            return "Expired"
        hours = int(diff // 3600)
        minutes = int((diff % 3600) // 60)
        if hours < 24:
            return f"{hours}h {minutes}m left"
        days, rem_hours = divmod(hours, 24)
        return f"{days}d {rem_hours}h {minutes}m left"
    except Exception:
        return expiry_str


def _read_saved_key():
    for path in SAVED_KEY_FILES:
        if os.path.exists(path):
            try:
                with open(path) as f:
                    val = f.read().strip().upper()
                    if val:
                        return val
            except Exception:
                pass
    return None


def _save_key(key):
    for path in SAVED_KEY_FILES:
        try:
            with open(path, "w") as f:
                f.write(key)
        except Exception:
            pass


def _clear_saved_keys():
    for path in SAVED_KEY_FILES:
        if os.path.exists(path):
            try:
                os.remove(path)
            except Exception:
                pass


def check_license():
    """
    Full flow: maintenance check -> local cache -> HWID lookup -> trial issue
    -> prompt for paid key. Returns (name, key, expiry) or None.
    """
    status = _api_get("status.php")
    if status and status.get("maintenance"):
        print("\n[!] System is under maintenance. Please try again later.\n")
        sys.exit()

    hwid = get_hwid()
    saved_key = _read_saved_key()

    # 1. Try the cached key
    if saved_key:
        result = _api_post("check.php", {"hwid": hwid, "key": saved_key})
        if result and result.get("ok") and result.get("valid"):
            return result.get("name", "USER"), result.get("key", saved_key), result.get("expires_at")
        _clear_saved_keys()

    # 2. HWID-only lookup (covers reinstalls where the local file was wiped)
    result = _api_post("check.php", {"hwid": hwid, "key": ""})
    if result and result.get("ok") and result.get("valid"):
        _save_key(result["key"])
        return result.get("name", "USER"), result["key"], result.get("expires_at")

    # 3. First-time device -> try auto trial
    device_model = get_device_model()
    android_version = get_android_version()
    trial = _api_post("trial.php", {
        "hwid": hwid,
        "device_model": device_model,
        "android_version": android_version,
        "app_version": APP_VERSION,
    })
    if trial and trial.get("ok") and trial.get("granted"):
        _save_key(trial["key"])
        print("\n[✓] 2-day free trial activated for this device!\n")
        time.sleep(1)
        return "FREE TRIAL USER", trial["key"], trial.get("expires_at")

    # 4. Fallback: ask for a paid key
    print("\n[!] Access denied or trial expired. Please enter a license key.\n")
    name = input("Enter your name: ").strip().upper() or "USER"
    key = input("Enter your license key: ").strip().upper()

    activation = _api_post("activate.php", {
        "key": key,
        "hwid": hwid,
        "name": name,
        "device_model": device_model,
        "android_version": android_version,
        "app_version": APP_VERSION,
    })

    if activation and activation.get("ok") and activation.get("valid"):
        _save_key(activation["key"])
        return name, activation["key"], activation.get("expires_at")

    reason = (activation or {}).get("error", "unknown_error")
    print(f"\n[×] License activation failed: {reason}\n")
    sys.exit()


if __name__ == "__main__":
    result = check_license()
    if result:
        user_name, user_key, expiry = result
        print(f"Welcome, {user_name}! Key: {user_key} | {calculate_time_left(expiry)}")
        _api_post("log_usage.php", {"key": user_key})
