#!/usr/bin/env python3
"""Build a compact menu review summary from candidate browser smoke payloads."""
from __future__ import annotations

import argparse
import html
import json
from pathlib import Path
from typing import Any


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

SOURCE_FILES = {
    "shop": "candidate_shop_menu_browser_smoke.json",
    "party": "candidate_party_join_browser_smoke.json",
    "skill": "candidate_skill_menu_browser_smoke.json",
    "equipment": "candidate_equipment_menu_browser_smoke.json",
    "status": "candidate_status_menu_browser_smoke.json",
    "progress": "candidate_progress_browser_smoke.json",
}

TOP_LEVEL_FIELDS = {
    "shop": ["status", "shopMenu", "shopCandidateMenu", "shopPurchase", "shopSale"],
    "party": ["status", "join", "joinMenu", "followerRender", "dialogueJoin"],
    "skill": ["status", "skillMenu", "skillMemberMenu"],
    "equipment": ["status", "equipmentMenu", "equipmentTargetMenu", "equipmentEquip", "equipmentBattleEffect"],
    "status": ["status", "statusMenu", "statusMemberMenu", "newGameStatusMenu"],
    "progress": ["status", "record", "restore"],
}


def load_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8")) if path.exists() else {}


def copy_fields(source: dict[str, Any], fields: list[str]) -> dict[str, Any]:
    return {field: source.get(field) for field in fields if field in source}


def menu_rows(payload: dict[str, Any], *path: str) -> Any:
    node: Any = payload
    for key in path:
        if not isinstance(node, dict):
            return None
        node = node.get(key)
    return node


def compact_shop(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["shop"])
    row["snapshots"] = {
        "shopMenu": {
            "shopMenu": {
                "rows": menu_rows(payload, "snapshots", "shopMenu", "shopMenu", "rows") or [],
            },
        },
    }
    return row


def compact_party(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["party"])
    row["snapshots"] = {
        "joinMenu": {
            "afterOpenItems": menu_rows(payload, "snapshots", "joinMenu", "afterOpenItems") or [],
        },
        "join": {
            "savedProgress": {
                "events": menu_rows(payload, "snapshots", "join", "savedProgress", "events") or [],
            },
        },
        "dialogueJoin": {
            "savedProgress": {
                "events": menu_rows(payload, "snapshots", "dialogueJoin", "savedProgress", "events") or [],
            },
        },
        "followerRender": {
            "actorCollisionTargets": menu_rows(payload, "snapshots", "followerRender", "actorCollisionTargets") or [],
        },
    }
    return row


def compact_skill(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["skill"])
    row["snapshots"] = {
        "skillMenu": {
            "skillMenu": {
                "rows": menu_rows(payload, "snapshots", "skillMenu", "skillMenu", "rows") or [],
            },
        },
    }
    return row


def compact_equipment(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["equipment"])
    row["snapshots"] = {
        "equipmentMenu": {
            "equipmentMenu": {
                "rows": menu_rows(payload, "snapshots", "equipmentMenu", "equipmentMenu", "rows") or [],
            },
        },
    }
    return row


def compact_status(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["status"])
    row["snapshots"] = {
        "statusMenu": {
            "statusMenu": menu_rows(payload, "snapshots", "statusMenu", "statusMenu") or {},
        },
        "newGameStatusMenu": {
            "statusMenu": menu_rows(payload, "snapshots", "newGameStatusMenu", "statusMenu") or {},
        },
    }
    return row


def compact_progress(payload: dict[str, Any]) -> dict[str, Any]:
    row = copy_fields(payload, TOP_LEVEL_FIELDS["progress"])
    row["snapshots"] = {
        "restore": {
            "storyFlagReview": menu_rows(payload, "snapshots", "restore", "storyFlagReview") or {},
        },
    }
    return row


COMPACTORS = {
    "shop": compact_shop,
    "party": compact_party,
    "skill": compact_skill,
    "equipment": compact_equipment,
    "status": compact_status,
    "progress": compact_progress,
}


def build_summary(root: Path = ROOT) -> dict[str, Any]:
    out_dir = root / "out"
    menus: dict[str, Any] = {}
    sources: dict[str, Any] = {}
    for key, name in SOURCE_FILES.items():
        path = out_dir / name
        payload = load_json(path)
        compact = COMPACTORS[key](payload)
        compact["sourceFile"] = f"out/{name}"
        menus[key] = compact
        source_size = path.stat().st_size if path.exists() else 0
        compact_size = len(json.dumps(compact, ensure_ascii=False, separators=(",", ":")).encode("utf-8"))
        sources[key] = {
            "sourceFile": f"out/{name}",
            "sourceSizeBytes": source_size,
            "compactSizeBytes": compact_size,
            "status": compact.get("status", "missing"),
        }
    return {
        "kind": "hwanse-menu-candidate-review-summary",
        "source": "tools/summarize_menu_candidate_review.py",
        "status": "ready",
        "sourceFiles": SOURCE_FILES,
        "boundary": (
            "Compact browser menu review contract. It keeps only fields used by web/menu_review.html; "
            "raw candidate browser smoke payloads remain audit/build inputs until their other consumers are replaced."
        ),
        "sources": sources,
        "menus": menus,
    }


def html_page(summary: dict[str, Any]) -> str:
    rows = "\n".join(
        "<tr>"
        f"<td id=\"{html.escape(key)}\"><code>{html.escape(key)}</code></td>"
        f"<td>{html.escape(str(info.get('status', '-')))}</td>"
        f"<td><code>{html.escape(str(info.get('sourceFile', '-')))}</code></td>"
        f"<td>{int(info.get('sourceSizeBytes') or 0):,}</td>"
        f"<td>{int(info.get('compactSizeBytes') or 0):,}</td>"
        "</tr>"
        for key, info in summary["sources"].items()
    )
    return f"""<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <title>Menu Candidate Review Summary</title>
  <style>
    body {{ margin: 24px; color: #202124; font-family: system-ui, sans-serif; line-height: 1.5; }}
    table {{ width: 100%; border-collapse: collapse; margin: 14px 0 28px; }}
    th, td {{ border: 1px solid #d7dce2; padding: 6px 8px; text-align: left; vertical-align: top; }}
    th {{ background: #f4f6f8; }}
    code {{ background: #f4f6f8; padding: 1px 4px; }}
  </style>
</head>
<body>
  <h1>Menu Candidate Review Summary</h1>
  <p>{html.escape(summary['boundary'])}</p>
  <table>
    <thead><tr><th>menu</th><th>status</th><th>raw source</th><th>raw bytes</th><th>compact bytes</th></tr></thead>
    <tbody>{rows}</tbody>
  </table>
</body>
</html>
"""


def write_outputs(summary: dict[str, Any], out_dir: Path = OUT) -> None:
    out_dir.mkdir(parents=True, exist_ok=True)
    (out_dir / "menu_candidate_review_summary.json").write_text(
        json.dumps(summary, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    (out_dir / "menu_candidate_review_summary.html").write_text(html_page(summary), encoding="utf-8")


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--root", type=Path, default=ROOT)
    parser.add_argument("--out-dir", type=Path, default=OUT)
    args = parser.parse_args()
    summary = build_summary(args.root)
    write_outputs(summary, args.out_dir)
    print(f"wrote menu candidate review summary -> {args.out_dir / 'menu_candidate_review_summary.html'}")


if __name__ == "__main__":
    main()
