"""CLI for managing accounts, VMs, and projects.

Usage:
  proxym-ctl accounts list
  proxym-ctl accounts add --name "Work" --provider anthropic --key sk-ant-...
  proxym-ctl accounts costs
  proxym-ctl vm list
  proxym-ctl vm create --name windsurf-work --tool windsurf --mount ~/projects
  proxym-ctl vm start windsurf-work
  proxym-ctl vm switch windsurf-work --project ~/other-project
  proxym-ctl status
"""

from __future__ import annotations

import argparse
import json
import sys

import httpx


def _client(base: str = "http://localhost:4000", key: str = "sk-proxy-local-dev"):
    return httpx.Client(
        base_url=base,
        headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
        timeout=10,
    )


def _print_json(data):
    print(json.dumps(data, indent=2, ensure_ascii=False))


def _print_table(rows: list[dict], columns: list[str], widths: list[int] | None = None):
    if not rows:
        print("  (empty)")
        return
    if not widths:
        widths = [max(len(c), max(len(str(r.get(c, ""))[:40]) for r in rows)) for c in columns]
    header = "  ".join(c.ljust(w) for c, w in zip(columns, widths))
    print(f"\033[1m{header}\033[0m")
    print("  ".join("─" * w for w in widths))
    for r in rows:
        line = "  ".join(str(r.get(c, ""))[:w].ljust(w) for c, w in zip(columns, widths))
        print(line)


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

def cmd_status(args):
    c = _client(args.proxy, args.key)
    try:
        health = c.get("/health").json()
        budget = c.get("/v1/budget").json()
        costs = c.get("/dashboard/costs").json()
        system = c.get("/dashboard/system").json()
    except httpx.ConnectError:
        print(f"\033[31mCannot connect to proxy at {args.proxy}\033[0m")
        sys.exit(1)

    print(f"\033[1m=== AI Proxy Status ===\033[0m")
    print(f"  Version:  {health.get('version', '?')}")
    print(f"  Budget:   ${budget.get('daily_remaining_usd', 0):.2f}/day remaining, "
          f"${budget.get('monthly_remaining_usd', 0):.2f}/month remaining")
    print(f"  Accounts: {costs.get('accounts_active', 0)}/{costs.get('accounts_count', 0)} active")
    print(f"  Costs:    ${costs.get('daily_total_usd', 0):.4f} today, "
          f"${costs.get('monthly_total_usd', 0):.4f} this month")
    print(f"  Requests: {costs.get('total_requests', 0)} total")
    by = costs.get("by_provider", {})
    if by:
        print(f"  By provider: {', '.join(f'{k}=${v:.4f}' for k, v in by.items())}")
    libvirt = system.get("libvirt", {})
    if any(libvirt.values()):
        print(f"  Libvirt:  {'✓' if libvirt.get('libvirt') else '✗'} libvirt, "
              f"{'✓' if libvirt.get('qemu') else '✗'} qemu")


def cmd_accounts_list(args):
    c = _client(args.proxy, args.key)
    data = c.get("/dashboard/accounts").json()
    accounts = data.get("accounts", [])
    if not accounts:
        print("No accounts configured. Use: proxym-ctl accounts add ...")
        return
    rows = []
    for a in accounts:
        rows.append({
            "id": a["id"],
            "name": a["name"],
            "provider": a["provider"],
            "plan": a.get("plan", ""),
            "active": "✓" if a["active"] else "✗",
            "budget": a.get("over_budget", False) and "OVER" or "ok",
            "daily$": f"${a['usage']['daily_cost']:.4f}",
            "total$": f"${a['usage']['total_cost']:.4f}",
            "reqs": str(a["usage"]["total_requests"]),
            "tools": str(len(a.get("tools", []))),
        })
    _print_table(rows, ["id", "name", "provider", "plan", "active", "budget", "daily$", "total$", "reqs", "tools"])


def cmd_accounts_add(args):
    c = _client(args.proxy, args.key)
    body = {
        "name": args.name,
        "provider": args.provider,
        "api_key": args.api_key or "",
        "email": args.email or "",
        "daily_budget_usd": args.daily_budget,
        "monthly_budget_usd": args.monthly_budget,
        "tags": args.tags.split(",") if args.tags else [],
    }
    result = c.post("/dashboard/accounts", json=body).json()
    print(f"\033[32mAccount created: {result.get('id')} ({result.get('name')})\033[0m")


def cmd_accounts_costs(args):
    c = _client(args.proxy, args.key)
    data = c.get("/dashboard/costs/detailed").json()
    summary = data.get("summary", {})
    print(f"\033[1m=== Cost Summary ===\033[0m")
    print(f"  Today:    ${summary.get('daily_total_usd', 0):.4f}")
    print(f"  Month:    ${summary.get('monthly_total_usd', 0):.4f}")
    print(f"  Requests: {summary.get('total_requests', 0)}")
    print()
    accounts = data.get("accounts", [])
    if accounts:
        rows = []
        for a in accounts:
            budget = a.get("budget", {})
            rows.append({
                "name": a["name"],
                "provider": a["provider"],
                "daily": f"${a['daily_cost']:.4f}",
                "monthly": f"${a['monthly_cost']:.4f}",
                "reqs": str(a["daily_requests"]),
                "remaining": f"${budget.get('daily_remaining_usd', 0):.2f}/d" if budget else "-",
                "status": "⚠ OVER" if a.get("over_budget") else "✓",
            })
        _print_table(rows, ["name", "provider", "daily", "monthly", "reqs", "remaining", "status"])


def cmd_vm_list(args):
    c = _client(args.proxy, args.key)
    data = c.get("/dashboard/vms").json()
    vms = data.get("vms", [])
    if not vms:
        print("No VMs configured. Use: proxym-ctl vm create ...")
        return
    rows = []
    for v in vms:
        rows.append({
            "id": v["id"],
            "name": v["name"],
            "state": v["state"],
            "tool": v.get("tool", ""),
            "ip": v.get("ip", ""),
            "mount": v.get("code_mount", ""),
        })
    _print_table(rows, ["id", "name", "state", "tool", "ip", "mount"])


def cmd_vm_create(args):
    c = _client(args.proxy, args.key)
    body = {
        "name": args.name,
        "tool": args.tool or "",
        "account_id": args.account or "",
        "vcpus": args.cpus,
        "memory_mb": args.memory,
        "code_mount_host": args.mount or "",
        "base_image": args.image,
    }
    result = c.post("/dashboard/vms", json=body).json()
    print(f"\033[32mVM created: {result.get('id')} ({result.get('name')})\033[0m")


def cmd_vm_action(args):
    c = _client(args.proxy, args.key)
    result = c.post(f"/dashboard/vms/{args.vm_id}/{args.action}").json()
    if result.get("ok"):
        print(f"\033[32mVM {args.vm_id}: {args.action} OK\033[0m")
    else:
        print(f"\033[31mVM {args.vm_id}: {args.action} FAILED\033[0m")


def cmd_vm_switch(args):
    c = _client(args.proxy, args.key)
    result = c.post(f"/dashboard/vms/{args.vm_id}/switch-project",
                    json={"project_path": args.project}).json()
    if result.get("ok"):
        print(f"\033[32mVM {args.vm_id}: switched to {args.project}\033[0m")
    else:
        print(f"\033[31mFailed to switch project\033[0m")


def cmd_models(args):
    c = _client(args.proxy, args.key)
    data = c.get("/v1/models").json()
    models = data.get("data", [])
    rows = []
    for m in models:
        in_cost = m["input_cost_per_1m"]
        out_cost = m["output_cost_per_1m"]
        rows.append({
            "model": m["id"],
            "provider": m["owned_by"],
            "in$/1M": "FREE" if in_cost == 0 else f"${in_cost:.2f}",
            "out$/1M": "FREE" if out_cost == 0 else f"${out_cost:.2f}",
            "ctx": f"{m['context_window'] // 1000}K",
            "tiers": m["tier_range"],
        })
    _print_table(rows, ["model", "provider", "in$/1M", "out$/1M", "ctx", "tiers"])


# ── Main ─────────────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(prog="proxym-ctl", description="AI Proxy Control CLI")
    parser.add_argument("--proxy", default="http://localhost:4000", help="Proxy URL")
    parser.add_argument("--key", default="sk-proxy-local-dev", help="API key")

    sub = parser.add_subparsers(dest="command")

    # status
    sub.add_parser("status", help="Show system status")

    # models
    sub.add_parser("models", help="List available models")

    # accounts
    acct = sub.add_parser("accounts", help="Manage accounts")
    acct_sub = acct.add_subparsers(dest="acct_cmd")
    acct_sub.add_parser("list", help="List accounts")
    acct_sub.add_parser("costs", help="Show cost breakdown")
    add_p = acct_sub.add_parser("add", help="Add account")
    add_p.add_argument("--name", required=True)
    add_p.add_argument("--provider", required=True)
    add_p.add_argument("--api-key", default="")
    add_p.add_argument("--email", default="")
    add_p.add_argument("--daily-budget", type=float, default=5.0)
    add_p.add_argument("--monthly-budget", type=float, default=60.0)
    add_p.add_argument("--tags", default="")

    # vm
    vm = sub.add_parser("vm", help="Manage VMs")
    vm_sub = vm.add_subparsers(dest="vm_cmd")
    vm_sub.add_parser("list", help="List VMs")
    create_p = vm_sub.add_parser("create", help="Create VM")
    create_p.add_argument("--name", required=True)
    create_p.add_argument("--tool", default="")
    create_p.add_argument("--account", default="")
    create_p.add_argument("--mount", default="")
    create_p.add_argument("--cpus", type=int, default=2)
    create_p.add_argument("--memory", type=int, default=4096)
    create_p.add_argument("--image", default="fedora-40-dev")

    for action in ["start", "stop", "pause", "resume", "snapshot"]:
        act_p = vm_sub.add_parser(action, help=f"{action.title()} a VM")
        act_p.add_argument("vm_id")

    switch_p = vm_sub.add_parser("switch", help="Switch project mount")
    switch_p.add_argument("vm_id")
    switch_p.add_argument("--project", required=True)

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        return

    dispatch = {
        "status": cmd_status,
        "models": cmd_models,
    }

    if args.command in dispatch:
        dispatch[args.command](args)
    elif args.command == "accounts":
        acct_dispatch = {
            "list": cmd_accounts_list,
            "add": cmd_accounts_add,
            "costs": cmd_accounts_costs,
        }
        if args.acct_cmd in acct_dispatch:
            acct_dispatch[args.acct_cmd](args)
        else:
            acct.print_help()
    elif args.command == "vm":
        if args.vm_cmd == "list":
            cmd_vm_list(args)
        elif args.vm_cmd == "create":
            cmd_vm_create(args)
        elif args.vm_cmd == "switch":
            cmd_vm_switch(args)
        elif args.vm_cmd in ("start", "stop", "pause", "resume", "snapshot"):
            args.action = args.vm_cmd
            cmd_vm_action(args)
        else:
            vm.print_help()


if __name__ == "__main__":
    main()
