#!/usr/bin/env python3
"""Build a compact battle-skill timeline browser smoke summary."""
from __future__ import annotations

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


ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "out"
SOURCE_FILE = "battle_skill_timeline_browser_smoke.json"
SUMMARY_FILE = "battle_skill_timeline_browser_summary.json"


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


def compact_json_size(payload: Any) -> int:
    return len(json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8"))


def check_id(row: Any) -> dict[str, Any]:
    if not isinstance(row, dict):
        return {}
    return {
        "ownerKey": row.get("ownerKey"),
        "ownerName": row.get("ownerName"),
        "skillIdHex": row.get("skillIdHex"),
        "skillName": row.get("skillName"),
        "levelOrFixed": row.get("levelOrFixed"),
        "status": row.get("status"),
    }


def requirement_id(row: Any) -> dict[str, Any]:
    if not isinstance(row, dict):
        return {}
    return {
        "rowId": row.get("rowId"),
        "ownerKey": row.get("ownerKey"),
        "skillIdHex": row.get("skillIdHex"),
        "levelOrFixed": row.get("levelOrFixed"),
        "requirement": row.get("requirement"),
        "status": row.get("status"),
        "hasActivePreviewCanvas": row.get("hasActivePreviewCanvas"),
        "hasNonemptyEffectCanvas": row.get("hasNonemptyEffectCanvas"),
    }


def build_timeline(payload: dict[str, Any]) -> dict[str, Any]:
    checks = payload.get("checks") or []
    effect_checks = payload.get("effectChecks") or []
    requirement_checks = payload.get("executionRequirementChecks") or []
    requirement_buckets = payload.get("checkedExecutionRequirementBuckets") or []
    status_counts = Counter(str((row or {}).get("status")) for row in checks if isinstance(row, dict))
    effect_status_counts = Counter(str((row or {}).get("status")) for row in effect_checks if isinstance(row, dict))
    requirement_status_counts = Counter(str((row or {}).get("status")) for row in requirement_checks if isinstance(row, dict))
    requirement_bucket_counts = Counter(str(bucket) for bucket in requirement_buckets)
    return {
        "status": payload.get("status"),
        "kind": payload.get("kind"),
        "base": payload.get("base"),
        "sourceFile": f"out/{SOURCE_FILE}",
        "checkedRows": payload.get("checkedRows"),
        "checkedEffectRows": payload.get("checkedEffectRows"),
        "checkedExecutionRequirementRows": payload.get("checkedExecutionRequirementRows"),
        "checkedExecutionRequirementBuckets": requirement_buckets,
        "checkStatusCounts": dict(sorted(status_counts.items())),
        "effectCheckStatusCounts": dict(sorted(effect_status_counts.items())),
        "executionRequirementStatusCounts": dict(sorted(requirement_status_counts.items())),
        "executionRequirementBucketCounts": dict(sorted(requirement_bucket_counts.items())),
        "checks": [check_id(row) for row in checks],
        "effectCheckSamples": [check_id(row) for row in effect_checks[:24]],
        "executionRequirementSamples": [requirement_id(row) for row in requirement_checks[:80]],
    }


def build_summary(root: Path = ROOT) -> dict[str, Any]:
    out_dir = root / "out"
    source_path = out_dir / SOURCE_FILE
    payload = load_json(source_path)
    timeline = build_timeline(payload)
    return {
        "kind": "hwanse-battle-skill-timeline-browser-summary",
        "source": "tools/summarize_battle_skill_timeline_browser.py",
        "status": "ready",
        "sourceFile": f"out/{SOURCE_FILE}",
        "boundary": (
            "Compact browser smoke contract for battle-skill timeline goal audits. "
            "It keeps pass status, coverage counts, execution requirement buckets, "
            "and checked regression row identities. The raw smoke remains verifier "
            "output for pixel/detail guards and visual assertion builders."
        ),
        "sourceSizeBytes": source_path.stat().st_size if source_path.exists() else 0,
        "compactSizeBytes": compact_json_size(timeline),
        "timeline": timeline,
    }


def html_page(summary: dict[str, Any]) -> str:
    timeline = summary["timeline"]
    rows = []
    for key, value in timeline.items():
        rows.append(
            "<tr>"
            f"<td><code>{html.escape(str(key))}</code></td>"
            f"<td>{html.escape(json.dumps(value, ensure_ascii=False, separators=(',', ':')))[:2200]}</td>"
            "</tr>"
        )
    return f"""<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <title>Battle Skill Timeline Browser 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>Battle Skill Timeline Browser Summary</h1>
  <p>{html.escape(summary['boundary'])}</p>
  <p><code>{html.escape(summary['sourceFile'])}</code>: {int(summary['sourceSizeBytes']):,} bytes raw, {int(summary['compactSizeBytes']):,} bytes compact.</p>
  <table>
    <thead><tr><th>Field</th><th>Compact Value</th></tr></thead>
    <tbody>{''.join(rows)}</tbody>
  </table>
</body>
</html>
"""


def write_outputs(
    summary: dict[str, Any],
    out_dir: Path = OUT,
    html_out: Path | None = None,
) -> Path:
    out_dir.mkdir(parents=True, exist_ok=True)
    json_out = out_dir / SUMMARY_FILE
    json_out.write_text(
        json.dumps(summary, ensure_ascii=False, separators=(",", ":"), sort_keys=True),
        encoding="utf-8",
    )
    if html_out is not None:
        html_out.parent.mkdir(parents=True, exist_ok=True)
        html_out.write_text(html_page(summary), encoding="utf-8")
    return json_out


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--root", type=Path, default=ROOT)
    parser.add_argument("--out-dir", type=Path, default=OUT)
    parser.add_argument("--html-out", type=Path)
    args = parser.parse_args()
    summary = build_summary(args.root)
    json_out = write_outputs(summary, args.out_dir, args.html_out)
    print(f"wrote battle skill timeline browser summary -> {json_out}")


if __name__ == "__main__":
    main()
