#!/usr/bin/env python3
"""
process-wiki-system-changes
Propagates wiki changes to star-map.json and SQLite.

Wiki pages (wiki/star-systems/*/index.md) are the single source of truth.
This script:
  1. Reads all wiki frontmatter
  2. Updates star-map.json nodes (preserving edges/topology)
  3. Syncs all data into SQLite star_systems table
  4. Reports completion stats

Usage:
    tooling/process-wiki-system-changes           Run full sync
    tooling/process-wiki-system-changes --dry-run  Show what would change
    tooling/process-wiki-system-changes --stats    Just show fill rates
"""

import argparse
import json
import sys
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
WORKTREE_ROOT = (SCRIPT_DIR / "..").resolve()
STAR_MAP_PATH = WORKTREE_ROOT / "docs" / "design" / "star-map.json"

# Import wiki_sync for DB operations
sys.path.insert(0, str(SCRIPT_DIR / "db"))
import wiki_sync


# ---------------------------------------------------------------------------
# Star-map.json update
# ---------------------------------------------------------------------------

# Fields that star-map.json nodes carry (topology + join keys)
STAR_MAP_NODE_FIELDS = [
    "system_id", "astronomical_id",
    "gate_topology", "aperture_count", "gate_connections",
    "hop_distance_from_gateway",
]


def update_star_map(wiki_systems: dict) -> dict:
    """Update star-map.json node fields from wiki data. Returns summary."""
    with open(STAR_MAP_PATH, "r") as f:
        data = json.load(f)

    nodes = data["nodes"]
    updated = 0
    added = 0
    wiki_sids = set(wiki_systems.keys())
    map_sids = {n["system_id"] for n in nodes}

    # Update existing nodes
    for node in nodes:
        sid = node["system_id"]
        if sid not in wiki_systems:
            continue

        wiki = wiki_systems[sid]
        changed = False
        for field in STAR_MAP_NODE_FIELDS:
            if field in wiki and wiki[field] != "":
                val = wiki[field]
                # Coerce integers
                if field in ("aperture_count", "gate_connections", "hop_distance_from_gateway"):
                    try:
                        val = int(val)
                    except (ValueError, TypeError):
                        continue
                if node.get(field) != val:
                    node[field] = val
                    changed = True

        # Preserve is_gateway flag
        if changed:
            updated += 1

    # Add nodes for wiki pages that aren't in star-map yet
    for sid in wiki_sids - map_sids:
        wiki = wiki_systems[sid]
        new_node = {"system_id": sid}
        for field in STAR_MAP_NODE_FIELDS:
            if field in wiki and wiki[field] != "":
                val = wiki[field]
                if field in ("aperture_count", "gate_connections", "hop_distance_from_gateway"):
                    try:
                        val = int(val)
                    except (ValueError, TypeError):
                        continue
                new_node[field] = val
        nodes.append(new_node)
        added += 1

    with open(STAR_MAP_PATH, "w") as f:
        json.dump(data, f, indent=2)
        f.write("\n")

    return {
        "nodes": len(nodes),
        "edges": len(data["edges"]),
        "updated": updated,
        "added": added,
    }


def dry_run(wiki_systems: dict) -> dict:
    """Show what would change in star-map.json without writing."""
    with open(STAR_MAP_PATH, "r") as f:
        data = json.load(f)

    changes = []
    for node in data["nodes"]:
        sid = node["system_id"]
        if sid not in wiki_systems:
            continue
        wiki = wiki_systems[sid]
        for field in STAR_MAP_NODE_FIELDS:
            if field in wiki and wiki[field] != "":
                val = wiki[field]
                if field in ("aperture_count", "gate_connections", "hop_distance_from_gateway"):
                    try:
                        val = int(val)
                    except (ValueError, TypeError):
                        continue
                if node.get(field) != val:
                    changes.append(f"  {sid}.{field}: {node.get(field)} -> {val}")

    return {"changes": changes}


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------


def main():
    parser = argparse.ArgumentParser(
        description="Propagate wiki changes to star-map.json and SQLite"
    )
    parser.add_argument("--dry-run", action="store_true", help="Show changes without writing")
    parser.add_argument("--stats", action="store_true", help="Just show fill rates")
    args = parser.parse_args()

    cfg = wiki_sync.load_config()

    if args.stats:
        wiki_sync.stats(cfg)
        return

    # Load wiki
    wiki_systems, warnings, body_count = wiki_sync.load_wiki_pages()
    if not wiki_systems:
        print("ERROR: No wiki pages found")
        for w in warnings:
            print(f"  {w}")
        sys.exit(1)

    print(f"Loaded {len(wiki_systems)} wiki pages ({body_count} body sections filled)")
    if warnings:
        print(f"Warnings: {len(warnings)}")
        for w in warnings[:5]:
            print(f"  {w}")
        if len(warnings) > 5:
            print(f"  ... and {len(warnings) - 5} more")

    if args.dry_run:
        result = dry_run(wiki_systems)
        if result["changes"]:
            print(f"\nstar-map.json changes ({len(result['changes'])}):")
            for c in result["changes"]:
                print(c)
        else:
            print("\nstar-map.json: no changes")
        print("\n(dry run — nothing written)")
        return

    # Step 1: Update star-map.json
    print("\n--- Updating star-map.json ---")
    map_result = update_star_map(wiki_systems)
    print(f"Nodes: {map_result['nodes']}, Edges: {map_result['edges']}")
    print(f"Updated: {map_result['updated']}, Added: {map_result['added']}")

    # Step 2: Sync to SQLite
    print("\n--- Syncing to SQLite ---")
    db_result = wiki_sync.sync(cfg)
    if db_result["ok"]:
        print(db_result["summary"])
    else:
        print(f"ERROR: {db_result.get('error')}")
        sys.exit(1)

    # Step 3: Quick stats
    print("\n--- Completion ---")
    wiki_sync.stats(cfg)


if __name__ == "__main__":
    main()
