#!/usr/bin/env python3
"""CLI for license management.

Usage:
    python -m mesh.scripts.license_admin create --customer "Acme Corp" --email admin@acme.com --tier professional --max-nodes 50 --months 12
    python -m mesh.scripts.license_admin list
    python -m mesh.scripts.license_admin validate <key>
    python -m mesh.scripts.license_admin deactivate <key>
    python -m mesh.scripts.license_admin telemetry <key>

Set MESH_LICENSE_SERVER to point to a remote server (default: http://localhost:8450).
Set MESH_LICENSE_ADMIN_KEY for admin authentication.
Set MESH_LICENSE_DB to use a local database directly.
"""
from __future__ import annotations

import argparse
import json
import os
import sys
from datetime import datetime, timedelta
from pathlib import Path

# Ensure project root is on path
_project_root = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(_project_root))


def _get_mode():
    """Determine whether to use local DB or remote server."""
    server = os.environ.get("MESH_LICENSE_SERVER", "")
    db_path = os.environ.get("MESH_LICENSE_DB", "data/licenses.db")
    if server:
        return "remote", server
    return "local", db_path


def _admin_key():
    return os.environ.get("MESH_LICENSE_ADMIN_KEY", "mesh-admin-secret")


# ── Remote helpers ───────────────────────────────────────────────────────────


def _remote_post(server: str, path: str, data: dict = None):
    import httpx
    headers = {"X-Admin-Key": _admin_key()}
    resp = httpx.post(f"{server}{path}", json=data, headers=headers, timeout=10)
    return resp


def _remote_get(server: str, path: str):
    import httpx
    headers = {"X-Admin-Key": _admin_key()}
    resp = httpx.get(f"{server}{path}", headers=headers, timeout=10)
    return resp


# ── Commands ─────────────────────────────────────────────────────────────────


def cmd_create(args):
    mode, target = _get_mode()
    if mode == "remote":
        resp = _remote_post(target, "/licenses", {
            "customer_name": args.customer,
            "customer_email": args.email,
            "tier": args.tier,
            "max_nodes": args.max_nodes,
            "duration_months": args.months,
        })
        if resp.status_code == 200:
            data = resp.json()
            print(f"License created:")
            print(f"  Key:      {data['license_key']}")
            print(f"  Tier:     {data['tier']}")
            print(f"  Nodes:    {data['max_nodes']}")
            print(f"  Expires:  {data['expires_at']}")
        else:
            print(f"Error: {resp.status_code} — {resp.text}", file=sys.stderr)
            sys.exit(1)
    else:
        from mesh.licensing.server import LicenseDB
        from mesh.licensing.keygen import generate_license_key
        from mesh.licensing.models import LicenseRecord, LicenseTier, TIER_DEFAULTS

        tier = LicenseTier(args.tier)
        defaults = TIER_DEFAULTS[tier]
        now = datetime.utcnow()

        record = LicenseRecord(
            customer_name=args.customer,
            customer_email=args.email,
            license_key=generate_license_key(),
            tier=tier,
            max_nodes=args.max_nodes if args.max_nodes is not None else defaults["max_nodes"],
            features=defaults["features"],
            issued_at=now,
            expires_at=now + timedelta(days=30 * args.months),
            active=True,
        )

        db = LicenseDB(target)
        record = db.create_license(record)
        db.close()

        print(f"License created:")
        print(f"  Key:      {record.license_key}")
        print(f"  Tier:     {record.tier.value}")
        print(f"  Nodes:    {record.max_nodes}")
        print(f"  Customer: {record.customer_name}")
        print(f"  Expires:  {record.expires_at}")


def cmd_list(args):
    mode, target = _get_mode()
    if mode == "remote":
        resp = _remote_get(target, "/admin/licenses")
        if resp.status_code == 200:
            licenses = resp.json()
            if not licenses:
                print("No licenses found.")
                return
            print(f"{'Key':<26} {'Tier':<14} {'Customer':<20} {'Nodes':<6} {'Active':<7} {'Expires'}")
            print("-" * 100)
            for lic in licenses:
                print(f"{lic['license_key']:<26} {lic['tier']:<14} {lic['customer_name']:<20} "
                      f"{lic['max_nodes']:<6} {lic['active']!s:<7} {lic.get('expires_at', 'N/A')}")
        else:
            print(f"Error: {resp.status_code} — {resp.text}", file=sys.stderr)
            sys.exit(1)
    else:
        from mesh.licensing.server import LicenseDB
        db = LicenseDB(target)
        licenses = db.list_licenses()
        db.close()

        if not licenses:
            print("No licenses found.")
            return
        print(f"{'Key':<26} {'Tier':<14} {'Customer':<20} {'Nodes':<6} {'Active':<7} {'Expires'}")
        print("-" * 100)
        for lic in licenses:
            print(f"{lic.license_key:<26} {lic.tier.value:<14} {lic.customer_name:<20} "
                  f"{lic.max_nodes:<6} {lic.active!s:<7} {lic.expires_at}")


def cmd_validate(args):
    mode, target = _get_mode()
    if mode == "remote":
        resp = _remote_get(target, f"/licenses/{args.key}")
        if resp.status_code == 200:
            data = resp.json()
            print(f"License valid: {data['valid']}")
            print(f"  Tier:     {data['tier']}")
            print(f"  Customer: {data['customer_name']}")
            print(f"  Nodes:    {data['max_nodes']}")
            print(f"  Features: {', '.join(data['features'])}")
            print(f"  Expires:  {data['expires_at']}")
        else:
            print(f"License invalid or not found: {resp.status_code}", file=sys.stderr)
            sys.exit(1)
    else:
        from mesh.licensing.server import LicenseDB, _record_to_info
        db = LicenseDB(target)
        record = db.get_license(args.key)
        db.close()

        if not record:
            print("License not found.", file=sys.stderr)
            sys.exit(1)

        info = _record_to_info(record)
        print(f"License valid: {info.valid}")
        print(f"  Tier:     {info.tier.value}")
        print(f"  Customer: {info.customer_name}")
        print(f"  Nodes:    {info.max_nodes}")
        print(f"  Features: {', '.join(info.features)}")
        print(f"  Expires:  {info.expires_at}")


def cmd_deactivate(args):
    mode, target = _get_mode()
    if mode == "remote":
        resp = _remote_post(target, f"/licenses/{args.key}/deactivate")
        if resp.status_code == 200:
            print(f"License {args.key} deactivated.")
        else:
            print(f"Error: {resp.status_code} — {resp.text}", file=sys.stderr)
            sys.exit(1)
    else:
        from mesh.licensing.server import LicenseDB
        db = LicenseDB(target)
        ok = db.deactivate_license(args.key)
        db.close()
        if ok:
            print(f"License {args.key} deactivated.")
        else:
            print("License not found.", file=sys.stderr)
            sys.exit(1)


def cmd_telemetry(args):
    mode, target = _get_mode()
    if mode == "remote":
        resp = _remote_get(target, f"/licenses/{args.key}/usage")
        if resp.status_code == 200:
            data = resp.json()
            print(f"Usage for {args.key}:")
            print(f"  Total heartbeats:   {data['total_heartbeats']}")
            print(f"  Peak nodes:         {data['peak_nodes']}")
            print(f"  Active days (30d):  {data['daily_active_nodes']}")
            print(f"  Last heartbeat:     {data.get('last_heartbeat', 'N/A')}")
            if data.get("telemetry_history"):
                print(f"  Recent entries:     {len(data['telemetry_history'])}")
        else:
            print(f"Error: {resp.status_code} — {resp.text}", file=sys.stderr)
            sys.exit(1)
    else:
        from mesh.licensing.server import LicenseDB
        db = LicenseDB(target)
        usage = db.get_usage(args.key)
        db.close()
        print(f"Usage for {args.key}:")
        print(f"  Total heartbeats:   {usage.total_heartbeats}")
        print(f"  Peak nodes:         {usage.peak_nodes}")
        print(f"  Active days (30d):  {usage.daily_active_nodes}")
        print(f"  Last heartbeat:     {usage.last_heartbeat}")


def main():
    parser = argparse.ArgumentParser(
        description="Mesh Optimizer License Administration",
        prog="python -m mesh.scripts.license_admin",
    )
    sub = parser.add_subparsers(dest="command", required=True)

    # create
    p_create = sub.add_parser("create", help="Create a new license")
    p_create.add_argument("--customer", required=True, help="Customer name")
    p_create.add_argument("--email", required=True, help="Customer email")
    p_create.add_argument("--tier", default="professional",
                          choices=["community", "professional", "enterprise"])
    p_create.add_argument("--max-nodes", type=int, default=None, help="Max nodes (default: tier default)")
    p_create.add_argument("--months", type=int, default=12, help="License duration in months")

    # list
    sub.add_parser("list", help="List all licenses")

    # validate
    p_val = sub.add_parser("validate", help="Validate a license key")
    p_val.add_argument("key", help="License key")

    # deactivate
    p_deact = sub.add_parser("deactivate", help="Deactivate a license")
    p_deact.add_argument("key", help="License key")

    # telemetry
    p_tel = sub.add_parser("telemetry", help="View telemetry for a license")
    p_tel.add_argument("key", help="License key")

    args = parser.parse_args()

    commands = {
        "create": cmd_create,
        "list": cmd_list,
        "validate": cmd_validate,
        "deactivate": cmd_deactivate,
        "telemetry": cmd_telemetry,
    }
    commands[args.command](args)


if __name__ == "__main__":
    main()
