#!/usr/bin/env python3
"""claude-rc-envs — list / inspect / remove Claude Remote Control environments.

Account-wide view (the same list the claude.ai/code environment picker shows),
across every host. Reads the OAuth token from the macOS Keychain (Claude Code)
or ~/.claude/.credentials.json.

Usage:
  claude-rc-envs                 # table: state, host, project, dir
  claude-rc-envs --json          # raw JSON
  claude-rc-envs rm <env_id>     # delete an environment (e.g. an orphan)
  claude-rc-envs archive <id>    # archive instead of delete
"""
import json
import os
import platform
import subprocess
import sys
import urllib.error
import urllib.request

API = "https://api.anthropic.com/v1/environments"
BETA = "environments-2025-11-01"


def token() -> str:
    if platform.system() == "Darwin":
        try:
            out = subprocess.run(
                ["security", "find-generic-password", "-s", "Claude Code-credentials", "-w"],
                capture_output=True, text=True, timeout=10,
            )
            if out.returncode == 0 and out.stdout.strip():
                return json.loads(out.stdout)["claudeAiOauth"]["accessToken"]
        except Exception:
            pass
    path = os.path.expanduser("~/.claude/.credentials.json")
    if os.path.exists(path):
        with open(path) as fh:
            return json.load(fh)["claudeAiOauth"]["accessToken"]
    sys.exit("claude-rc-envs: no Claude credentials found (Keychain or ~/.claude/.credentials.json)")


def call(method: str, url: str) -> dict:
    req = urllib.request.Request(url, method=method, headers={
        "Authorization": f"Bearer {token()}",
        "anthropic-beta": BETA,
        "anthropic-version": "2023-06-01",
        "content-type": "application/json",
    })
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            body = resp.read()
            return json.loads(body) if body else {}
    except urllib.error.HTTPError as e:
        sys.exit(f"claude-rc-envs: HTTP {e.code} {e.reason}: {e.read().decode()[:200]}")
    except urllib.error.URLError as e:
        sys.exit(f"claude-rc-envs: network error: {e.reason}")


def fetch() -> list:
    return call("GET", API).get("data", [])


def row(e: dict):
    c = e.get("config", {})
    bridge = c.get("type") == "bridge"
    host = c.get("machine_name") or ("cloud" if not bridge else "?")
    name = e.get("name", "")
    project = name.split(":")[1] if bridge and name.count(":") >= 1 else name
    return e.get("state", "?"), host, project, e.get("id", ""), c.get("directory", "")


def list_envs():
    rows = [row(e) for e in fetch()]
    if not rows:
        print("(no environments)")
        return
    wh = max(4, *(len(r[1]) for r in rows))
    wp = max(7, *(len(r[2]) for r in rows))
    print(f"{'STATE':8} {'HOST':{wh}} {'PROJECT':{wp}} {'ENV ID':20} DIR")
    for state, host, project, env_id, directory in rows:
        print(f"{state:8} {host:{wh}} {project:{wp}} {env_id:20} {directory}")


def main():
    args = sys.argv[1:]
    if not args:
        return list_envs()
    cmd = args[0]
    if cmd in ("--json", "json"):
        print(json.dumps(fetch(), indent=2))
    elif cmd in ("rm", "delete", "--rm"):
        if len(args) < 2:
            sys.exit("usage: claude-rc-envs rm <env_id>")
        call("DELETE", f"{API}/{args[1]}")
        print(f"removed {args[1]}")
    elif cmd in ("archive", "--archive"):
        if len(args) < 2:
            sys.exit("usage: claude-rc-envs archive <env_id>")
        call("POST", f"{API}/{args[1]}/archive")
        print(f"archived {args[1]}")
    elif cmd in ("ls", "list", "status", "envs"):
        list_envs()
    else:
        sys.exit(f"claude-rc-envs: unknown command '{cmd}' (try: ls | --json | rm <id> | archive <id>)")


if __name__ == "__main__":
    main()
