#!/usr/bin/env python3
"""Emergency Sunshine pairing bypass — extract client cert from log and inject into state file.

Sunshine v2026.516.143833 has a broken PIN validation pipeline. The /api/pin endpoint
deadlocks internally even when IP addresses match. This script:
  1. Reads the most recent /pair request's clientcert from sunshine.log
  2. Decodes the hex-encoded PEM cert
  3. Injects it directly into sunshine_state.json as a pre-paired named_device
  4. Restarts Sunshine

After running, Moonlight must be FULLY CLOSED AND REOPENED — it will see the pre-paired
cert and skip the PIN screen.

Usage:
  python3 pairing-bypass-inject-cert.py [--restart]

Requirements:
  - Root not needed (Sunshine runs as the same user)
  - sunshine_state.json must be writable
  - Moonlight must have sent at least one /pair request (visible in sunshine.log)
"""

import json
import re
import uuid
import sys
import os
import subprocess
import time

SUNSHINE_LOG = os.path.expanduser("~/.config/sunshine/sunshine.log")
SUNSHINE_STATE = os.path.expanduser("~/.config/sunshine/sunshine_state.json")
SUNSHINE_CONF = os.path.expanduser("~/.config/sunshine/sunshine.conf")

def extract_latest_cert():
    with open(SUNSHINE_LOG, "r", encoding="utf-8", errors="replace") as f:
        content = f.read()
    matches = re.findall(r'clientcert -- ([0-9a-fA-F]+)', content)
    if not matches:
        print("ERROR: No clientcert found in sunshine.log")
        print("Make sure Moonlight has tried to pair (it should show a PIN screen)")
        sys.exit(1)
    hex_cert = matches[-1]
    pem_cert = bytes.fromhex(hex_cert).decode("utf-8")
    print(f"Extracted certificate ({len(pem_cert)} bytes)")
    print(f"Preview: {pem_cert[:60]}...")
    return pem_cert

def inject_cert(pem_cert, client_name="RE-PC"):
    try:
        with open(SUNSHINE_STATE, "r") as f:
            state = json.load(f)
    except (FileNotFoundError, json.JSONDecodeError):
        state = {}

    if "root" not in state:
        state["root"] = {"uniqueid": "0123456789ABCDEF", "named_devices": []}
    if "named_devices" not in state["root"]:
        state["root"]["named_devices"] = []

    # Check if client already exists — update cert
    updated = False
    for dev in state["root"]["named_devices"]:
        if dev.get("name") == client_name:
            dev["cert"] = pem_cert
            dev["enabled"] = "true"
            updated = True
            print(f"Updated existing client '{client_name}'")
            break

    if not updated:
        state["root"]["named_devices"].append({
            "name": client_name,
            "cert": pem_cert,
            "uuid": str(uuid.uuid4()).upper(),
            "enabled": "true"
        })
        print(f"Added new client '{client_name}'")

    # Ensure origin_pin_allowed = pc for easier future pairing
    try:
        with open(SUNSHINE_CONF, "r") as f:
            conf = f.read()
        if "origin_pin_allowed" not in conf:
            with open(SUNSHINE_CONF, "a") as f:
                f.write("\norigin_pin_allowed = pc\n")
            print("Added origin_pin_allowed = pc to sunshine.conf")
    except FileNotFoundError:
        pass

    with open(SUNSHINE_STATE, "w") as f:
        json.dump(state, f, indent=4)
    print(f"Injected into {SUNSHINE_STATE}")

def restart_sunshine():
    print("Restarting Sunshine...")
    subprocess.run(["systemctl", "--user", "restart", "sunshine"], check=False)
    time.sleep(3)
    result = subprocess.run(
        ["systemctl", "--user", "status", "sunshine", "--no-pager"],
        capture_output=True, text=True
    )
    if "active (running)" in result.stdout:
        print("Sunshine is running.")
    else:
        print("WARNING: Sunshine may not have started. Check: systemctl --user status sunshine")

def main():
    restore = "--restart" in sys.argv
    cert = extract_latest_cert()
    inject_cert(cert, client_name=os.environ.get("MOONLIGHT_CLIENT_NAME", "RE-PC"))
    if restore:
        restart_sunshine()
    else:
        print("\nNow restart Sunshine:  systemctl --user restart sunshine")
    print("\nIMPORTANT: Fully CLOSE Moonlight on the client, then reopen it.")
    print("It should connect directly to apps without asking for a PIN.")

if __name__ == "__main__":
    main()
