#!/usr/bin/env python3
"""Prepare local directories for original-runtime battle effect captures.

This helper does not capture the original game.  It creates a row-by-row local
workspace with small metadata files so original PNG frames can be dropped into
the exact directory layout consumed by
``tools/import_battle_effect_original_captures.py``.
"""

from __future__ import annotations

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


ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "out"
DEFAULT_OUTPUT = ROOT / "captures" / "battle_effect_original_capture_inbox"
PLAN = OUT / "battle_effect_pixel_oracle_plan.json"


def read_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8"))


def safe_row_dir(value: str | None) -> str:
    text = str(value or "row")
    return "".join(ch if ch.isalnum() or ch in "._-" else "_" for ch in text).strip("._") or "row"


def display_path(path: Path) -> str:
    try:
        return str(path.relative_to(ROOT))
    except ValueError:
        return str(path)


def load_rows(scope: str) -> list[dict[str, Any]]:
    plan = read_json(PLAN)
    if scope == "first-pass":
        rows = plan.get("recommendedFirstPassRows") or []
    elif scope == "full":
        rows = plan.get("fullOracleRows") or []
    else:
        raise ValueError(f"unknown scope: {scope}")
    if not rows:
        raise RuntimeError(f"{PLAN} has no rows for scope {scope!r}")
    return rows


def row_metadata(row: dict[str, Any]) -> dict[str, Any]:
    return {
        "id": row.get("id"),
        "ownerKey": row.get("ownerKey"),
        "ownerName": row.get("ownerName"),
        "skillIdHex": row.get("skillIdHex"),
        "levelOrFixed": row.get("levelOrFixed"),
        "skillName": row.get("skillName"),
        "renderTrack": row.get("renderTrack"),
        "effectAnimationClass": row.get("effectAnimationClass"),
        "executionRequirements": row.get("executionRequirements") or [],
        "helperBehaviorClasses": row.get("helperBehaviorClasses") or [],
        "effectFrameCount": row.get("effectFrameCount"),
        "captureRules": [
            "Capture original game output at 640x480 without scaling or filtering.",
            "Put PNG frames for this row directly in this original/ directory.",
            "Keep frame order stable by filename, e.g. tick_00000.png, tick_00048.png.",
            "The web reference side is compared separately by row id.",
        ],
    }


def readme_text(row: dict[str, Any]) -> str:
    reqs = row.get("executionRequirements") or []
    behaviors = row.get("helperBehaviorClasses") or []
    return "\n".join(
        [
            f"Battle effect original capture row: {row.get('id')}",
            "",
            f"Owner: {row.get('ownerName') or row.get('ownerKey')}",
            f"Skill: {row.get('skillName')} ({row.get('skillIdHex')})",
            f"Level/fixed: {row.get('levelOrFixed')}",
            f"Render track: {row.get('renderTrack')}",
            f"Effect class: {row.get('effectAnimationClass')}",
            f"Effect frame count: {row.get('effectFrameCount')}",
            "",
            "Execution requirements:",
            *(f"- {item}" for item in reqs),
            "",
            "Helper behavior classes:",
            *(f"- {item}" for item in behaviors),
            "",
            "Drop original runtime PNG frames here.",
            "Use 640x480 unscaled output, sorted filenames, and no filtering.",
            "",
        ]
    )


def prepare(args: argparse.Namespace) -> dict[str, Any]:
    rows = load_rows(args.scope)
    output_root = args.output_root.resolve()
    created: list[dict[str, Any]] = []
    for row in rows:
        row_id = str(row["id"])
        row_dir = output_root / safe_row_dir(row_id)
        original_dir = row_dir / "original"
        metadata_path = row_dir / "capture_request.json"
        readme_path = original_dir / "README.txt"
        if args.write:
            original_dir.mkdir(parents=True, exist_ok=True)
            metadata_path.write_text(json.dumps(row_metadata(row), ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
            readme_path.write_text(readme_text(row), encoding="utf-8")
        created.append(
            {
                "id": row_id,
                "directory": display_path(original_dir),
                "metadata": display_path(metadata_path),
            }
        )
    return {
        "scope": args.scope,
        "write": args.write,
        "outputRoot": display_path(output_root),
        "rows": len(rows),
        "directories": created,
        "nextImportCommand": (
            f"python3 tools/import_battle_effect_original_captures.py {display_path(output_root)} "
            f"--scope {args.scope} --copy"
        ),
    }


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--scope", choices=["first-pass", "full"], default="first-pass")
    parser.add_argument("--output-root", type=Path, default=DEFAULT_OUTPUT)
    parser.add_argument("--write", action="store_true", help="Create directories and metadata files")
    args = parser.parse_args()
    print(json.dumps(prepare(args), ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
