#!/usr/bin/env python3
"""Build candidate map links from save selector scene-reference leaves."""
from __future__ import annotations

import argparse
import html
import json
from pathlib import Path


OUT = Path(__file__).resolve().parents[1] / "out"


def unique(values: list[str]) -> list[str]:
    seen = set()
    result = []
    for value in values:
        if value in seen:
            continue
        seen.add(value)
        result.append(value)
    return result


def build_links(reference_rows: list[dict]) -> dict[str, dict]:
    leaves: dict[tuple[str, str], list[dict]] = {}
    for row in reference_rows:
        if row.get("kind") != "fieldMap" or not row.get("sceneMatched"):
            continue
        path = row.get("pathHex") or []
        if not path:
            continue
        leaves.setdefault((row["label"], path[-1]), []).append(row)

    result: dict[str, dict] = {}
    for (label, leaf), rows in sorted(leaves.items()):
        maps = unique([row["resource"] for row in rows])
        if len(maps) < 2:
            continue
        for source in maps:
            targets = [name for name in maps if name != source]
            entry = result.setdefault(source, {"fieldMaps": [], "records": []})
            entry["fieldMaps"] = unique([*entry["fieldMaps"], *targets])
            entry["records"].append(
                {
                    "source": source,
                    "selector": label,
                    "leafPointerHex": leaf,
                    "fieldMaps": maps,
                    "targets": targets,
                    "scenes": [
                        {
                            "map": row["resource"],
                            "recordVaHex": row["refVaHex"],
                            "sceneIdHex": row.get("sceneIdHex"),
                            "tilesets": row.get("tilesets") or [],
                        }
                        for row in rows
                    ],
                }
            )
    return dict(sorted(result.items()))


def markdown(links: dict[str, dict]) -> str:
    lines = [
        "# Save Selector Scene Links",
        "",
        "Candidate map links inferred from field-map scene records that share the same save-selector pointer leaf. These are not confirmed tile transitions.",
        "",
        f"Source maps: {len(links)}.",
        "",
        "| source | targets | selector leaves | open |",
        "| --- | --- | --- | --- |",
    ]
    for source, entry in links.items():
        leaves = unique([f"{record['selector']} {record['leafPointerHex']}" for record in entry["records"]])
        targets = ", ".join(f"[{name}](../web/game.html?map={name})" for name in entry["fieldMaps"])
        lines.append(
            f"| {source} | {targets or '-'} | {', '.join(leaves)} | [open](../web/game.html?map={source}&events=1&overview=1) |"
        )
    lines.append("")
    return "\n".join(lines)


def html_page(links: dict[str, dict]) -> str:
    rows = []
    for source, entry in links.items():
        target_links = " ".join(
            f'<a href="../web/game.html?map={html.escape(name)}">{html.escape(name)}</a>'
            for name in entry["fieldMaps"]
        )
        leaves = ", ".join(
            html.escape(f"{record['selector']} {record['leafPointerHex']}")
            for record in entry["records"]
        )
        rows.append(
            "\n".join(
                [
                    "<tr>",
                    f'  <td><a href="../web/game.html?map={html.escape(source)}&amp;events=1&amp;overview=1">{html.escape(source)}</a></td>',
                    f'  <td class="links">{target_links or "-"}</td>',
                    f"  <td>{leaves}</td>",
                    "</tr>",
                ]
            )
        )
    return "\n".join(
        [
            "<!doctype html>",
            '<html lang="en">',
            "<head>",
            '  <meta charset="utf-8">',
            '  <meta name="viewport" content="width=device-width, initial-scale=1">',
            "  <title>Save Selector Scene Links</title>",
            "  <style>",
            "    body { margin: 24px; background: #101010; color: #eee; font: 14px system-ui, sans-serif; }",
            "    table { border-collapse: collapse; width: 100%; }",
            "    th, td { border: 1px solid #333; padding: 6px 8px; vertical-align: top; }",
            "    th { background: #1d1d1d; position: sticky; top: 0; }",
            "    a { color: #9bd4ff; }",
            "    .links { display: flex; flex-wrap: wrap; gap: 6px 10px; }",
            "  </style>",
            "</head>",
            "<body>",
            "  <h1>Save Selector Scene Links</h1>",
            "  <p>Candidate map links inferred from save-selector pointer leaves. These are not confirmed tile transitions.</p>",
            f"  <p>Source maps: {len(links)}.</p>",
            "  <table>",
            "    <thead><tr><th>source</th><th>targets</th><th>selector leaves</th></tr></thead>",
            "    <tbody>",
            *rows,
            "    </tbody>",
            "  </table>",
            "</body>",
            "</html>",
            "",
        ]
    )


def write_outputs(links: dict[str, dict], out_dir: Path = OUT) -> None:
    out_dir.mkdir(parents=True, exist_ok=True)
    (out_dir / "save_selector_scene_links.json").write_text(
        json.dumps(links, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    (out_dir / "save_selector_scene_links.js").write_text(
        "window.HWANSE_SAVE_SELECTOR_SCENE_LINKS = "
        + json.dumps(links, ensure_ascii=False, separators=(",", ":"))
        + ";\n",
        encoding="utf-8",
    )


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--references", type=Path, default=OUT / "save_scene_selector_references.json")
    parser.add_argument("--out-dir", type=Path, default=OUT)
    args = parser.parse_args()
    links = build_links(json.loads(args.references.read_text(encoding="utf-8")))
    write_outputs(links, args.out_dir)
    print(f"wrote {len(links)} save selector scene links -> {args.out_dir / 'save_selector_scene_links.json'}")


if __name__ == "__main__":
    main()
