# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""pulse friends — generate and manage friend access keys (full Pro, no Stripe)."""
import hashlib
import hmac
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional


def _get_friends_file() -> Path:
    from pulse.core.paths import get_pulse_home
    return get_pulse_home() / "friends.json"


def _load_friends() -> dict:
    f = _get_friends_file()
    if f.exists():
        try:
            return json.loads(f.read_text(encoding="utf-8"))
        except (json.JSONDecodeError, OSError):
            return {}
    return {}


def _save_friends(data: dict):
    f = _get_friends_file()
    f.parent.mkdir(parents=True, exist_ok=True)
    f.write_text(json.dumps(data, indent=2), encoding="utf-8")


def _generate_friend_key(name: str) -> Optional[str]:
    """Generate PULSE-FRIEND-{name}-{sig} using PULSE_BRAIN_KEY."""
    brain_key = os.environ.get("PULSE_BRAIN_KEY", "")
    if not brain_key:
        print("ERROR: PULSE_BRAIN_KEY not in environment. Check your .env file.")
        return None
    payload = f"friend:{name}"
    sig = hmac.new(brain_key.encode(), payload.encode(), hashlib.sha256).hexdigest()[:24]
    return f"PULSE-FRIEND-{name}-{sig}"


def cmd_friends(args: list):
    sub = args[0] if args else "list"

    if sub == "add":
        if len(args) < 2:
            print("Usage: pulse friends add <name>")
            return
        name = args[1].lower().replace(" ", "_")
        if not name.isidentifier():
            print(f"ERROR: Name '{name}' contains invalid characters. Use letters, numbers, underscores.")
            return
        friends = _load_friends()
        if name in friends and friends[name].get("active"):
            print(f"Friend '{name}' already active: {friends[name]['key']}")
            return
        key = _generate_friend_key(name)
        if not key:
            return
        friends[name] = {
            "key": key,
            "added_at": datetime.now(timezone.utc).isoformat(),
            "active": True,
        }
        _save_friends(friends)
        print(f"Friend key for '{name}':")
        print(f"\n  {key}\n")
        print("Share this key. They run:  pulse activate <key>")
        print()
        print("REQUIRED: Add PULSE_BRAIN_KEY to Vercel environment variables")
        print("so the validation endpoint can verify this key.")

    elif sub == "list":
        friends = _load_friends()
        if not friends:
            print("No friends yet. Run: pulse friends add <name>")
            return
        print(f"\n{'NAME':<20} {'STATUS':<10} {'KEY'}")
        print("-" * 80)
        for name, data in sorted(friends.items()):
            status = "active" if data.get("active") else "revoked"
            print(f"{name:<20} {status:<10} {data.get('key', '?')}")
        print()

    elif sub == "remove":
        if len(args) < 2:
            print("Usage: pulse friends remove <name>")
            return
        name = args[1].lower().replace(" ", "_")
        friends = _load_friends()
        if name not in friends:
            print(f"Friend '{name}' not found.")
            return
        key = friends[name].get("key", "")
        friends[name]["active"] = False
        _save_friends(friends)
        print(f"Revoked '{name}' locally.")
        print()
        print("To block server-side, add to FRIEND_REVOKE_LIST in Vercel env vars:")
        print(f"  {key}")

    else:
        print("Usage: pulse friends [add <name> | list | remove <name>]")
        print()
        print("  pulse friends add alice    — generate Pro key for alice")
        print("  pulse friends list         — show all friend keys")
        print("  pulse friends remove alice — revoke alice's access")
