#!/usr/bin/env python3
"""YNAB CLI tool — stdlib only (urllib + json)."""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error
from datetime import datetime, timedelta
from pathlib import Path

BASE_URL = "https://api.ynab.com/v1"
BUDGETS = {
    "family": "6c0a7a3f-6fa2-4729-9b88-d6ec3447fa69",
    "business": "6b38a734-c3a4-4efd-bdfb-9d317f896711",
}
DEFAULT_BUDGET = "family"


def load_api_key():
    p = Path.home() / ".openclaw" / "secrets" / "ynab-api-key.txt"
    if not p.exists():
        print(f"Error: API key not found at {p}", file=sys.stderr)
        sys.exit(1)
    return p.read_text().strip()


def api_get(path, api_key):
    url = f"{BASE_URL}{path}"
    req = urllib.request.Request(url, headers={
        "Authorization": f"Bearer {api_key}",
        "Accept": "application/json",
    })
    try:
        with urllib.request.urlopen(req) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        body = e.read().decode() if e.fp else ""
        print(f"API error {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


def fmt_amount(milliunits):
    """YNAB stores amounts in milliunits (1000 = $1.00)."""
    return milliunits / 1000


def money(milliunits):
    val = fmt_amount(milliunits)
    sign = "-" if val < 0 else ""
    return f"{sign}${abs(val):,.2f}"


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

def cmd_accounts(budget_id, api_key):
    data = api_get(f"/budgets/{budget_id}/accounts", api_key)
    accounts = [a for a in data["data"]["accounts"] if not a.get("closed", False) and not a.get("deleted", False)]
    accounts.sort(key=lambda a: a["type"])

    if not accounts:
        print("No open accounts found.")
        return

    cur_type = None
    for a in accounts:
        if a["type"] != cur_type:
            cur_type = a["type"]
            label = cur_type.replace("otherAsset", "Other Asset").replace("otherLiability", "Other Liability")
            print(f"\n  {label.upper()}")
        bal = money(a["balance"])
        print(f"    {a['name']:<35} {bal:>12}")

    total = sum(a["balance"] for a in accounts)
    print(f"\n  {'Net Worth':<37} {money(total):>12}")


def cmd_debt(budget_id, api_key):
    data = api_get(f"/budgets/{budget_id}/accounts", api_key)
    accounts = data["data"]["accounts"]
    debt_accts = [
        a for a in accounts
        if not a.get("closed", False)
        and not a.get("deleted", False)
        and a["balance"] < 0
    ]
    debt_accts.sort(key=lambda a: a["balance"])

    if not debt_accts:
        print("No debt accounts found. 🎉")
        return

    print("\n  DEBT ACCOUNTS")
    for a in debt_accts:
        print(f"    {a['name']:<35} {money(a['balance']):>12}")

    total = sum(a["balance"] for a in debt_accts)
    print(f"\n  {'Total Debt':<37} {money(total):>12}")


def cmd_summary(budget_id, api_key):
    now = datetime.now()
    month_str = now.strftime("%Y-%m-01")

    data = api_get(f"/budgets/{budget_id}/months/{month_str}", api_key)
    m = data["data"]["month"]

    income = m.get("income", 0)
    budgeted = m.get("budgeted", 0)
    activity = m.get("activity", 0)
    tbb = m.get("to_be_budgeted", 0)

    month_label = now.strftime("%B %Y")
    print(f"\n  {month_label} Summary")
    print(f"  {'─' * 40}")
    print(f"    {'Income':<30} {money(income):>12}")
    print(f"    {'Budgeted':<30} {money(budgeted):>12}")
    print(f"    {'Spent (Activity)':<30} {money(activity):>12}")
    print(f"    {'To Be Budgeted':<30} {money(tbb):>12}")


def cmd_budget(budget_id, api_key, month=None):
    if month:
        month_str = f"{month}-01"
        label = datetime.strptime(month, "%Y-%m").strftime("%B %Y")
    else:
        now = datetime.now()
        month_str = now.strftime("%Y-%m-01")
        label = now.strftime("%B %Y")

    data = api_get(f"/budgets/{budget_id}/months/{month_str}", api_key)
    cats = data["data"]["month"]["categories"]

    # Group by category group
    groups = {}
    for c in cats:
        if c.get("hidden", False) or c.get("deleted", False):
            continue
        gname = c.get("category_group_name", "Ungrouped")
        if gname == "Internal Master Category":
            continue
        groups.setdefault(gname, []).append(c)

    print(f"\n  Budget: {label}")
    print(f"  {'─' * 62}")
    print(f"    {'Category':<30} {'Budgeted':>10} {'Spent':>10} {'Balance':>10}")
    print(f"    {'─' * 60}")

    for gname, items in groups.items():
        print(f"\n  {gname}")
        for c in sorted(items, key=lambda x: x["name"]):
            b = money(c["budgeted"])
            a = money(c["activity"])
            bal = money(c["balance"])
            name = c["name"][:28]
            print(f"    {name:<30} {b:>10} {a:>10} {bal:>10}")


def cmd_transactions(budget_id, api_key, days=7):
    since = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
    data = api_get(f"/budgets/{budget_id}/transactions?since_date={since}", api_key)
    txns = data["data"]["transactions"]

    if not txns:
        print(f"No transactions in the last {days} days.")
        return

    txns.sort(key=lambda t: t["date"], reverse=True)

    print(f"\n  Transactions (last {days} days)")
    print(f"  {'─' * 72}")
    print(f"    {'Date':<12} {'Payee':<25} {'Category':<20} {'Amount':>12}")
    print(f"    {'─' * 70}")

    for t in txns:
        date = t["date"]
        payee = (t.get("payee_name") or "—")[:23]
        cat = (t.get("category_name") or "—")[:18]
        amt = money(t["amount"])
        print(f"    {date:<12} {payee:<25} {cat:<20} {amt:>12}")

    total = sum(t["amount"] for t in txns)
    print(f"\n    {'Total':<58} {money(total):>12}")


# ── CLI ──────────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(description="YNAB CLI tool")
    parser.add_argument("command", choices=["summary", "accounts", "debt", "budget", "transactions"])
    parser.add_argument("args", nargs="*", help="Command arguments (month YYYY-MM for budget, days for transactions)")
    parser.add_argument("--budget", choices=["family", "business"], default=DEFAULT_BUDGET,
                        help="Budget to use (default: family)")
    args = parser.parse_args()

    api_key = load_api_key()
    budget_id = BUDGETS[args.budget]

    if args.command == "accounts":
        cmd_accounts(budget_id, api_key)
    elif args.command == "debt":
        cmd_debt(budget_id, api_key)
    elif args.command == "summary":
        cmd_summary(budget_id, api_key)
    elif args.command == "budget":
        month = args.args[0] if args.args else None
        cmd_budget(budget_id, api_key, month)
    elif args.command == "transactions":
        days = int(args.args[0]) if args.args else 7
        cmd_transactions(budget_id, api_key, days)


if __name__ == "__main__":
    main()
