#!/usr/bin/env python3
"""Clean up duplicate GitHub issues and verify labels/milestones.

Usage: python tools/github-cleanup.py [--dry-run]

Closes known duplicate issues from the second seeder run, verifies labels
and milestones exist. Rate-limit aware (works within 60/hr).

The duplicate issue numbers are known from the two seeder runs:
- Run 1 (originals): #41-#96 (odd-ish numbers, 29 issues)
- Run 2 (duplicates): #44-#97 (even-ish numbers, 28 issues)
"""

from __future__ import annotations

import json
import subprocess
import sys
import time

REPO = "repos/LookNoHandsMom/LLMHosts.com"
DRY_RUN = "--dry-run" in sys.argv

# Known duplicate issue numbers from second seeder run.
# These have the same titles as the first run and should be closed.
# Source: seeder output log at /tmp/claude-1000/.../tasks/b158be0.output
DUPLICATE_ISSUES = [
    44,
    46,
    48,
    50,
    52,
    54,
    56,
    58,
    60,
    62,
    64,
    66,
    68,
    70,
    72,
    73,
    75,
    77,
    79,
    81,
    83,
    85,
    87,
    89,
    91,
    93,
    95,
    97,
]

# Required labels that may not exist yet
NEW_LABELS = [
    {"name": "epic:hive-ceo", "color": "0052CC", "description": "Embedded agent system"},
    {"name": "status:ready", "color": "0E8A16", "description": "Ready for implementation"},
    {"name": "status:in-progress", "color": "FBCA04", "description": "Currently being worked on"},
]


def gh_api(endpoint: str, method: str = "GET", data: dict | None = None) -> dict | list | None:
    """Call GitHub REST API via gh CLI with rate limit retry."""
    cmd = ["gh", "api", endpoint]
    if method != "GET":
        cmd.extend(["-X", method])
    if data:
        cmd.extend(["--input", "-"])
        result = subprocess.run(cmd, input=json.dumps(data), capture_output=True, text=True, timeout=30)
    else:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

    if result.returncode != 0:
        stderr = result.stderr.strip()
        if "rate limit" in stderr.lower() or "403" in stderr:
            print("  RATE LIMITED — waiting 65s...")
            time.sleep(65)
            return gh_api(endpoint, method, data)
        print(f"  ERROR: {stderr}")
        return None

    if result.stdout.strip():
        return json.loads(result.stdout)
    return None


def close_duplicates() -> int:
    """Close known duplicate issues from second seeder run."""
    closed = 0
    for issue_num in DUPLICATE_ISSUES:
        # Verify issue exists and is open before closing
        issue = gh_api(f"{REPO}/issues/{issue_num}")
        if not issue or "number" not in issue:
            print(f"  SKIP #{issue_num}: not found")
            continue
        if issue.get("state") == "closed":
            print(f"  SKIP #{issue_num}: already closed")
            continue

        title = issue.get("title", "???")
        print(f"  Close #{issue_num}: {title}")

        if not DRY_RUN:
            # Add comment explaining the closure
            gh_api(
                f"{REPO}/issues/{issue_num}/comments",
                method="POST",
                data={"body": "Duplicate from automated seeder re-run. Closing."},
            )
            time.sleep(1)
            # Close the issue
            gh_api(
                f"{REPO}/issues/{issue_num}",
                method="PATCH",
                data={"state": "closed", "state_reason": "not_planned"},
            )
            time.sleep(2)
        closed += 1
    return closed


def ensure_labels() -> int:
    """Create missing labels. Uses one API call to check, then creates as needed."""
    existing_labels_data = gh_api(f"{REPO}/labels?per_page=100")
    existing = {label["name"] for label in (existing_labels_data or [])}
    print(f"  Found {len(existing)} existing labels")

    created = 0
    for label in NEW_LABELS:
        if label["name"] not in existing:
            print(f"  Create: {label['name']}")
            if not DRY_RUN:
                gh_api(f"{REPO}/labels", method="POST", data=label)
                time.sleep(2)
            created += 1
    return created


def verify_milestones() -> dict[int, int]:
    """Verify milestones exist and return phase→ID mapping."""
    milestones = gh_api(f"{REPO}/milestones?per_page=10")
    if not milestones:
        print("  WARNING: No milestones found")
        return {}

    mapping: dict[int, int] = {}
    for ms in milestones:
        title = ms["title"]
        ms_num = ms["number"]
        if "Phase 1" in title:
            mapping[1] = ms_num
        elif "Phase 2" in title:
            mapping[2] = ms_num
        elif "Phase 3" in title:
            mapping[3] = ms_num
        elif "Phase 4" in title:
            mapping[4] = ms_num
        print(f"  Milestone #{ms_num}: {title}")

    return mapping


def main() -> None:
    print(f"GitHub Cleanup ({'DRY RUN' if DRY_RUN else 'LIVE'})")
    print()

    # Check rate limit
    rate = gh_api("rate_limit")
    if rate:
        remaining = rate["rate"]["remaining"]
        print(f"Rate limit: {remaining}/60 remaining")
        # Closing 28 dupes needs ~84 calls (fetch + comment + close per issue)
        # Plus labels (~4) and milestones (~1) = ~89 total
        # At 60/hr, this will take ~2 runs
        needed = len(DUPLICATE_ISSUES) * 3 + 5
        if remaining < 10:
            reset_time = rate["rate"]["reset"]
            wait = max(0, reset_time - time.time())
            print(f"Very low quota. Waiting {wait:.0f}s for reset...")
            time.sleep(wait + 5)
        elif remaining < needed:
            print(f"  NOTE: Need ~{needed} API calls. Have {remaining}. Will hit rate limit — re-run after reset.")
    print()

    # 1. Close duplicates
    print(f"Closing {len(DUPLICATE_ISSUES)} known duplicates...")
    closed = close_duplicates()
    print(f"  Closed: {closed}")
    print()

    # 2. Ensure labels
    print("Checking labels...")
    labels_created = ensure_labels()
    print(f"  Created: {labels_created}")
    print()

    # 3. Verify milestones
    print("Checking milestones...")
    mapping = verify_milestones()
    print(f"  Phase mapping: {mapping}")
    print()

    print("Done!")


if __name__ == "__main__":
    main()
