"""
Command-line management for the biosync licensing system.

    python3 -m license_server.manage genkeys
    python3 -m license_server.manage issue rigard@onyxdigital.co.za annual
    python3 -m license_server.manage users
    python3 -m license_server.manage licenses
    python3 -m license_server.manage payments
    python3 -m license_server.manage revoke LIC-ABC123
    python3 -m license_server.manage admin rigard@onyxdigital.co.za   # make an admin

Use this for one-off operations (generating the production signing keypair,
comping a license, auditing) without the web UI. Set BIOSYNC_PORTAL_DB to point at
the live database; defaults to license_server/portal.db.
"""

from __future__ import annotations

import os
import sys

DB_PATH = os.environ.get("BIOSYNC_PORTAL_DB", "license_server/portal.db")


def _db():
    from .db import DB
    return DB(DB_PATH)


def genkeys():
    """Generate a fresh Ed25519 keypair for production signing."""
    from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
    from cryptography.hazmat.primitives import serialization as s
    k = Ed25519PrivateKey.generate()
    priv = k.private_bytes(s.Encoding.Raw, s.PrivateFormat.Raw, s.NoEncryption()).hex()
    pub = k.public_key().public_bytes(s.Encoding.Raw, s.PublicFormat.Raw).hex()
    print("PRIVATE (server only — set BIOSYNC_LICENSE_PRIVKEY):\n  " + priv)
    print("\nPUBLIC (put in biosync/licensing.py LICENSE_PUBLIC_KEY_HEX, rebuild app):\n  " + pub)
    print("\nKeep the private key secret. If it leaks, anyone can mint keys.")


def issue(email, plan="annual", days=None):
    """Mint + assign a license key to an email (creates the account if new)."""
    import secrets
    from werkzeug.security import generate_password_hash
    from .app import grant_license
    db = _db()
    u = db.user_by_email(email)
    if not u:
        uid = db.create_user(email, "", "", generate_password_hash(secrets.token_hex(16)))
        u = db.user(uid)
        print(f"created account {email}")
    lic = grant_license(db, u, plan, int(days) if days else None)
    print(f"issued {lic['license_id']} ({lic['plan']}, expires {lic['expires']}) to {email}\n")
    print(lic["key"])


def users():
    db = _db()
    for u in db.all_users():
        lic = db.latest_license(u["id"]); pay = db.latest_payment(u["id"])
        print(f"{u['email']:<34} {'admin' if u['is_admin'] else '     '} "
              f"pay={pay['status'] if pay else 'none':<8} "
              f"lic={lic['status'] if lic else 'none'}")


def licenses():
    db = _db()
    for l in db.all_licenses():
        u = db.user(l["user_id"])
        print(f"{l['license_id']:<16} {l['status']:<8} {l['plan']:<8} exp {l['expires']}  {u['email'] if u else ''}")


def payments():
    db = _db()
    rows = db.q("SELECT * FROM payments ORDER BY id DESC")
    for p in rows:
        u = db.user(p["user_id"])
        print(f"{p['provider']:<8} {p['status']:<8} {p['currency']} {p['amount']/100:>10,.2f}  "
              f"{u['email'] if u else ''}  ref={p['provider_ref']}")


def revoke(license_id):
    db = _db()
    db.q("UPDATE licenses SET status='revoked' WHERE license_id=?", (license_id,))
    print(f"revoked {license_id}")


def admin(email):
    db = _db()
    db.q("UPDATE users SET is_admin=1 WHERE email=?", (email.lower(),))
    print(f"{email} is now an admin")


def main():
    args = sys.argv[1:]
    if not args:
        print(__doc__); return
    cmd, rest = args[0], args[1:]
    fns = {"genkeys": genkeys, "issue": issue, "users": users, "licenses": licenses,
           "payments": payments, "revoke": revoke, "admin": admin}
    fn = fns.get(cmd)
    if not fn:
        print(__doc__); sys.exit(1)
    fn(*rest)


if __name__ == "__main__":
    main()
