#!/usr/bin/env python3
"""
FLEET-010: Cross-Agent Task Delegation Protocol
Phase 3: Orchestration. Agents create issues, assign to other agents, review PRs.

Keyword-based heuristic assigns unassigned issues to the right agent:
- claw-code: small patches, config, docs, repo hygiene
- gemini: research, heavy implementation, architecture, debugging
- ezra: VPS, SSH, deploy, infrastructure, cron, ops
- bezalel: evennia, art, creative, music, visualization
- timmy: orchestration, review, deploy, fleet, pipeline

Usage:
  python3 delegation.py run     # Full cycle: scan, assign, report
  python3 delegation.py status  # Show current delegation state
  python3 delegation.py monitor # Check agent assignments for stuck items
"""

import os, sys, json, urllib.request
from datetime import datetime, timezone
from pathlib import Path

GITEA_BASE = "https://forge.alexanderwhitestone.com/api/v1"
TOKEN = Path(os.path.expanduser("~/.config/gitea/token")).read_text().strip()
DATA_DIR = Path(os.path.expanduser("~/.local/timmy/fleet-resources"))
LOG_FILE = DATA_DIR / "delegation.log"
HEADERS = {"Authorization": f"token {TOKEN}"}

AGENTS = {
    "claw-code": {"caps": ["patch","config","gitignore","cleanup","format","readme","typo"], "active": True},
    "gemini":    {"caps": ["research","investigate","benchmark","survey","evaluate","architecture","implementation"], "active": True},
    "ezra":      {"caps": ["vps","ssh","deploy","cron","resurrect","provision","infra","server"], "active": True},
    "bezalel":   {"caps": ["evennia","art","creative","music","visual","design","animation"], "active": True},
    "timmy":     {"caps": ["orchestrate","review","pipeline","fleet","monitor","health","deploy","ci"], "active": True},
}

MONITORED = [
    "Timmy_Foundation/timmy-home",
    "Timmy_Foundation/timmy-config",
    "Timmy_Foundation/the-nexus",
    "Timmy_Foundation/hermes-agent",
]

def api(path, method="GET", data=None):
    url = f"{GITEA_BASE}{path}"
    body = json.dumps(data).encode() if data else None
    hdrs = dict(HEADERS)
    if data: hdrs["Content-Type"] = "application/json"
    req = urllib.request.Request(url, data=body, headers=hdrs, method=method)
    try:
        resp = urllib.request.urlopen(req, timeout=15)
        raw = resp.read().decode()
        return json.loads(raw) if raw.strip() else {}
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"  API {e.code}: {body[:150]}")
        return None
    except Exception as e:
        print(f"  API error: {e}")
        return None

def log(msg):
    ts = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    with open(LOG_FILE, "a") as f: f.write(f"[{ts}] {msg}\n")

def suggest_agent(title, body):
    text = (title + " " + body).lower()
    for agent, info in AGENTS.items():
        for kw in info["caps"]:
            if kw in text:
                return agent, f"matched: {kw}"
    return None, None

def assign(repo, num, agent, reason=""):
    result = api(f"/repos/{repo}/issues/{num}", method="PATCH",
                 data={"assignees": {"operation": "set", "usernames": [agent]}})
    if result:
        api(f"/repos/{repo}/issues/{num}/comments", method="POST",
            data={"body": f"[DELEGATION] Assigned to {agent}. {reason}"})
        log(f"Assigned {repo}#{num} to {agent}: {reason}")
    return result

def run_cycle():
    log("--- Delegation cycle start ---")
    count = 0
    for repo in MONITORED:
        issues = api(f"/repos/{repo}/issues?state=open&limit=50")
        if not issues: continue
        for i in issues:
            if i.get("assignees"): continue
            title = i.get("title", "")
            body = i.get("body", "")
            if any(w in title.lower() for w in ["epic", "discussion"]): continue
            agent, reason = suggest_agent(title, body)
            if agent and AGENTS.get(agent, {}).get("active"):
                if assign(repo, i["number"], agent, reason): count += 1
    log(f"Cycle complete: {count} new assignments")
    print(f"Delegation cycle: {count} assignments")
    return count

def status():
    print("\n=== Delegation Dashboard ===")
    for agent, info in AGENTS.items():
        count = 0
        for repo in MONITORED:
            issues = api(f"/repos/{repo}/issues?state=open&limit=50")
            if issues:
                for i in issues:
                    for a in (i.get("assignees") or []):
                        if a.get("login") == agent: count += 1
        icon = "ON" if info["active"] else "OFF"
        print(f"  {agent:12s}: {count:>3} issues [{icon}]")

if __name__ == "__main__":
    cmd = sys.argv[1] if len(sys.argv) > 1 else "run"
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    if cmd == "status": status()
    elif cmd == "run":
        run_cycle()
        status()
    else: status()
