#!/usr/bin/env python3
"""
find-stubs — Find unwritten wiki system stubs by sector and hop range.

Usage:
    tooling/wiki/find-stubs west_reach 7 9
    tooling/wiki/find-stubs south_reach 3 5 --limit 10
    tooling/wiki/find-stubs --all-sectors 6 8

Outputs a markdown table with all data needed for batch planning.
A page is "written" if it has >36 lines.

Data sources:
- star-map.json: topology (adjacency, hop distance, apertures, gate_topology)
- wiki stubs: star type, sector, settlement wave (from READ-ONLY System Profile)
"""

import argparse
import json
import re
from pathlib import Path

STAR_MAP = Path(__file__).parent.parent.parent / "docs/design/star-map.json"
WIKI_DIR = Path(__file__).parent.parent.parent / "wiki/star-systems"
STUB_MAX_LINES = 36


def sid_to_dir(system_id: str) -> str:
    """Convert system_id like 'GJ 103' to directory name 'GJ-103'."""
    return system_id.replace(" ", "-")


def read_wiki(system_id: str) -> dict | None:
    """Read star type, sector, wave, and name from a wiki page."""
    f = WIKI_DIR / sid_to_dir(system_id) / "index.md"
    if not f.exists():
        return None
    lines = f.read_text().splitlines()
    info = {"lines": len(lines), "written": len(lines) > STUB_MAX_LINES}

    # Line 1: # Name
    if lines and lines[0].startswith("# "):
        info["name"] = lines[0][2:].strip()

    # Line 2: **GJ ID** | star-type | sector
    if len(lines) > 1:
        parts = lines[1].split("|")
        if len(parts) >= 3:
            info["star"] = parts[1].strip()
            info["sector"] = parts[2].strip()

    # Find settlement wave in System Profile table
    for line in lines:
        if "wave_" in line or "unsettled" in line:
            m = re.search(r"(wave_\d|unsettled)", line)
            if m:
                info["wave"] = m.group(1)
                break

    return info


def main():
    parser = argparse.ArgumentParser(description="Find unwritten wiki stubs")
    parser.add_argument("sector", nargs="?", help="Sector (e.g. west_reach)")
    parser.add_argument("hop_min", nargs="?", type=int, default=0)
    parser.add_argument("hop_max", nargs="?", type=int, default=99)
    parser.add_argument("--all-sectors", action="store_true")
    parser.add_argument("--limit", type=int, default=0)
    parser.add_argument("--written", action="store_true",
                        help="Show written pages instead of stubs")
    args = parser.parse_args()

    if args.all_sectors:
        if args.sector and args.sector.isdigit():
            args.hop_min = int(args.sector)
            if args.hop_min and args.hop_max == 99:
                pass  # keep default
        args.sector = None

    with open(STAR_MAP) as f:
        data = json.load(f)

    # Build node lookup and adjacency from star-map.json
    nodes = {n["system_id"]: n for n in data["nodes"]}
    adj: dict[str, list[str]] = {n["system_id"]: [] for n in data["nodes"]}
    for a, b in data["edges"]:
        adj[a].append(b)
        adj[b].append(a)

    results = []
    for sid, node in nodes.items():
        hop = node.get("hop_distance_from_gateway", 99)
        if hop < args.hop_min or hop > args.hop_max:
            continue

        wiki = read_wiki(sid)
        if not wiki:
            continue

        # Filter by sector
        sector = wiki.get("sector", "")
        if args.sector and sector != args.sector:
            continue

        # Filter by written status
        if args.written and not wiki["written"]:
            continue
        if not args.written and wiki["written"]:
            continue

        # Build neighbor info
        neighbors = []
        for n_sid in sorted(adj.get(sid, [])):
            n_wiki = read_wiki(n_sid)
            if n_wiki and n_wiki["written"]:
                neighbors.append(f"✓{sid_to_dir(n_sid)} ({n_wiki.get('name', '?')})")
            else:
                neighbors.append(f"·{sid_to_dir(n_sid)}")

        results.append({
            "hop": hop,
            "sid": sid,
            "star": wiki.get("star", "?"),
            "apertures": node.get("aperture_count", 0),
            "topology": node.get("gate_topology", "?"),
            "wave": wiki.get("wave", "?"),
            "neighbors": neighbors,
        })

    results.sort(key=lambda r: (r["hop"], r["sid"]))
    if args.limit:
        results = results[:args.limit]

    # Output
    sector_label = args.sector or "all sectors"
    mode = "written" if args.written else "stubs"
    print(f"## {mode.title()}: {sector_label} hops {args.hop_min}-{args.hop_max}")
    print(f"**Found {len(results)} systems**\n")

    print("| Hop | System | Star | Apt | Topology | Wave | Adjacent |")
    print("|-----|--------|------|-----|----------|------|----------|")
    for r in results:
        adj_str = ", ".join(r["neighbors"])
        print(f"| {r['hop']} | {r['sid']} | {r['star']} | {r['apertures']} "
              f"| {r['topology']} | {r['wave']} | {adj_str} |")

    # Summary stats
    if results:
        by_hop = {}
        for r in results:
            by_hop.setdefault(r["hop"], 0)
            by_hop[r["hop"]] += 1
        print(f"\n**By hop:** " + ", ".join(f"hop {h}: {c}" for h, c in sorted(by_hop.items())))


if __name__ == "__main__":
    main()
