#!/usr/bin/env python3
"""Consolidate the remaining static frontier for field map visible animation.

The map animation evidence is intentionally split across many focused reports.
This page keeps the decision boundary clear:

* layer1 bit 0x40 is a redraw/animated-cell consumer signal;
* the draw path uses ordinary tile-id -> source-rect conversion;
* resource roots for animated maps do not contain animation commands;
* active-object +0xec scripts and runtime +0x64 frame scripts do not contain
  command-boundary live tile writes;
* the offset-shift hypothesis is a visual/manual aid, not an EXE producer.
"""
from __future__ import annotations

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


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


def load_json(name: str) -> dict[str, Any]:
    try:
        data = json.loads((OUT / name).read_text(encoding="utf-8"))
    except FileNotFoundError:
        return {}
    return data if isinstance(data, dict) else {}


def summary(name: str) -> dict[str, Any]:
    value = load_json(name).get("summary")
    return value if isinstance(value, dict) else {}


def h(value: Any) -> str:
    return html.escape("" if value is None else str(value), quote=True)


def build() -> dict[str, Any]:
    tile = summary("map_animation_tile_review.json")
    exe_pattern = summary("map_animation_exe_pattern_review.json")
    resource = summary("map_animation_resource_binding_probe.json")
    live = summary("map_animation_live_buffer_writer_review.json")
    object_relative = summary("map_animation_object_relative_tile_write_review.json")
    redraw = summary("map_animation_redraw_consumer_review.json")
    draw_transform = summary("map_animation_draw_tile_transform_review.json")
    tick = summary("map_animation_tick_route_review.json")
    active_script = summary("map_animation_active_object_script_tile_write_review.json")
    frame_script = summary("map_animation_frame_script_tile_write_review.json")
    non_object = summary("map_animation_non_object_tile_write_root_review.json")
    specialized = summary("map_animation_specialized_loop_boundary_review.json")
    shift = summary("map_animation_shift_hypothesis_review.json")
    boundary = summary("map_animation_execution_boundary_review.json")

    surfaces = [
        {
            "surface": "layer1 0x40 flagged cells",
            "status": "consumer-grounded",
            "confidence": "high",
            "evidence": (
                f"animated maps={tile.get('animatedMapCount')}; cells={tile.get('animatedCellCount')}; "
                f"redraw path={redraw.get('redrawPathGrounded')}; flag consumer={redraw.get('layer1AnimatedFlagConsumerGrounded')}"
            ),
            "decision": "0x40 marks cells that participate in redraw/animation handling, but it is not itself the frame sequence.",
        },
        {
            "surface": "draw-time tile source transform",
            "status": "not-found",
            "confidence": "high-negative",
            "evidence": (
                f"tile rect formula={draw_transform.get('tileGridFormula')}; "
                f"uses 0x40={draw_transform.get('usesLayer1AnimatedFlag0x40')}; "
                f"uses frame counter={draw_transform.get('usesFrameCounter')}; "
                f"visible motion transform={draw_transform.get('drawTimeVisibleMotionTransformFound')}"
            ),
            "decision": "The inspected renderer draws the current live layer0 tile id normally; it does not shift source rects at draw time.",
        },
        {
            "surface": "animated map resource roots",
            "status": "resource-grounded-animation-command-unbound",
            "confidence": "high",
            "evidence": (
                f"maps with exact root={resource.get('mapsWithExactResourceRoot')}/"
                f"{resource.get('animatedMapCount')}; palette inside roots="
                f"{resource.get('paletteCommandInsideExactResourceRootCount')}; tile-write inside roots="
                f"{resource.get('tileWriteCommandInsideExactResourceRootCount')}"
            ),
            "decision": "Map resource package roots are not the visible animation loop roots.",
        },
        {
            "surface": "live layer0/layer1 tile write handlers",
            "status": "handler-grounded-producer-unbound",
            "confidence": "medium-high",
            "evidence": (
                f"candidate VM write refs={live.get('candidateVmTileWriteRefCount')}; "
                f"inside animated resource roots={live.get('candidateVmTileWriteRefsInsideAnimatedResourceRoots')}; "
                f"handler opcodes={live.get('handlerOpcodeCount')}"
            ),
            "decision": "Tile-write handlers exist, but the static pass has not connected them to animated-map execution.",
        },
        {
            "surface": "active-object +0xec scripts",
            "status": "negative-command-boundary",
            "confidence": "high-negative",
            "evidence": (
                f"strict scripts={active_script.get('strictObjectEcScriptCount')}; "
                f"command-boundary tile writes={active_script.get('commandBoundaryTileWriteCount')}; "
                f"raw candidates={active_script.get('rawTileWriteCandidateCount')}"
            ),
            "decision": "Raw byte coincidences exist but no strict active-object script decodes to a promoted live tile-write producer.",
        },
        {
            "surface": "runtime +0x64 frame scripts",
            "status": "negative-command-boundary",
            "confidence": "high-negative",
            "evidence": (
                f"opcode20 targets={frame_script.get('opcode20AttachTargetCount')}; "
                f"opcode18 state entries={frame_script.get('opcode18StateEntryTargetCount')}; "
                f"tile-write producer found={frame_script.get('frameScriptTileWriteProducerFound')}"
            ),
            "decision": "Runtime-installed frame scripts are grounded, but they do not contain promoted tile-write animation commands.",
        },
        {
            "surface": "non-object aligned tile-write roots",
            "status": "unpromoted",
            "confidence": "medium-high-negative",
            "evidence": (
                f"aligned commands={non_object.get('alignedTileWriteCommandCount')}; roots={non_object.get('uniqueRootCount')}; "
                f"direct animated evidence={non_object.get('directAnimatedEvidenceCommandCount')}; "
                f"promoted={non_object.get('promotedAnimatedProducerCommandCount')}"
            ),
            "decision": "Aligned VM-shaped tile writes exist, but none both binds to an animated map and writes the animated cells/tiles.",
        },
        {
            "surface": "specialized tick/draw loop",
            "status": "not-found",
            "confidence": "medium-high-negative",
            "evidence": (
                f"inspected windows={specialized.get('inspectedWindowCount')}; "
                f"direct callees={specialized.get('directCalleeCount')}; "
                f"strong candidates={specialized.get('strongSpecializedCandidateCount')}"
            ),
            "decision": "No separate specialized visible-motion producer was exposed in the inspected tick/draw windows.",
        },
        {
            "surface": "offset/row shift visual hypothesis",
            "status": "visual-aid-not-producer",
            "confidence": "manual-review-only",
            "evidence": f"classes={shift.get('classes')}; components={shift.get('componentCount')}",
            "decision": "This helps inspect how frames might look, but it is not EXE execution evidence.",
        },
    ]

    next_frontier = [
        "Search for an animated-map-specific state counter or tile-substitution table outside object +0xec/+0x64 script inventories.",
        "If continuing statically, prioritize functions that reference both map layer buffers and a small frame counter/state byte, not resource roots alone.",
        "Do not promote palette commands, offset-shift visuals, or raw tile-write byte coincidences without an execution route.",
        "Runtime observation would be useful only as a narrow watch on live layer0 writes/palette writes for map1_01a/map1_02b; static evidence remains preferred.",
    ]

    promoted = [row for row in surfaces if row["status"].endswith("producer-grounded")]
    return {
        "version": 1,
        "kind": "hwanse-map-animation-static-frontier-review",
        "sourceArtifacts": [
            "out/map_animation_tile_review.json",
            "out/map_animation_redraw_consumer_review.json",
            "out/map_animation_draw_tile_transform_review.json",
            "out/map_animation_resource_binding_probe.json",
            "out/map_animation_live_buffer_writer_review.json",
            "out/map_animation_active_object_script_tile_write_review.json",
            "out/map_animation_frame_script_tile_write_review.json",
            "out/map_animation_non_object_tile_write_root_review.json",
            "out/map_animation_specialized_loop_boundary_review.json",
            "out/map_animation_shift_hypothesis_review.json",
            "out/map_animation_execution_boundary_review.json",
        ],
        "summary": {
            "animatedMapCount": tile.get("animatedMapCount"),
            "animatedCellCount": tile.get("animatedCellCount"),
            "surfaceCount": len(surfaces),
            "consumerGrounded": bool(redraw.get("redrawPathGrounded")),
            "drawTimeTransformFound": bool(draw_transform.get("drawTimeVisibleMotionTransformFound")),
            "resourceRootsUnbound": bool(resource.get("allExactResourceRootsUnbound")),
            "activeObjectProducerFound": bool(active_script.get("activeObjectScriptTileWriteProducerFound")),
            "frameScriptProducerFound": bool(frame_script.get("frameScriptTileWriteProducerFound")),
            "specializedProducerFound": bool(specialized.get("specializedVisibleMotionProducerFound")),
            "visibleMotionExecutionBindingProven": bool(boundary.get("visibleMotionExecutionBindingProven")),
            "promotedProducerCount": len(promoted),
            "decision": (
                "The 0x40 redraw consumer is grounded, but no static producer has been promoted for visible fire/waterfall motion. "
                "Current evidence excludes draw-time source transform, animated resource roots, active-object scripts, frame scripts, "
                "non-object roots, specialized tick/draw loops, and pure offset-shift visuals as sufficient proof."
            ),
        },
        "surfaces": surfaces,
        "nextFrontier": next_frontier,
    }


def render_html(data: dict[str, Any]) -> str:
    cards = "".join(
        f"<div class='card'><b>{h(k)}</b><span>{h(v)}</span></div>"
        for k, v in data["summary"].items()
    )
    rows = "".join(
        "<tr>"
        f"<td><b>{h(row['surface'])}</b></td>"
        f"<td>{h(row['status'])}<br><small>{h(row['confidence'])}</small></td>"
        f"<td>{h(row['evidence'])}</td>"
        f"<td>{h(row['decision'])}</td>"
        "</tr>"
        for row in data["surfaces"]
    )
    frontier = "".join(f"<li>{h(item)}</li>" for item in data["nextFrontier"])
    return f"""<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Map Animation Static Frontier</title>
<style>
  :root {{ color-scheme: light dark; }}
  body {{ margin:24px; font-family:system-ui,-apple-system,Segoe UI,sans-serif; line-height:1.45; }}
  h1 {{ margin:0 0 8px; font-size:24px; }}
  .muted {{ color:#667085; }}
  .cards {{ display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:10px; margin:16px 0; }}
  .card {{ border:1px solid #d0d5dd; border-radius:8px; padding:10px 12px; background:rgba(127,127,127,.05); }}
  .card b {{ display:block; color:#667085; font-size:12px; }}
  .card span {{ font-family:ui-monospace,SFMono-Regular,Menlo,monospace; overflow-wrap:anywhere; }}
  .scroll {{ overflow-x:auto; }}
  table {{ width:100%; border-collapse:collapse; }}
  th,td {{ border:1px solid #d0d5dd; padding:7px 8px; vertical-align:top; }}
  th {{ text-align:left; background:rgba(127,127,127,.08); }}
  small {{ color:#667085; }}
</style>
<h1>Map Animation Static Frontier</h1>
<p class="muted">필드 맵 애니메이션의 소비/후보/배제 표면을 통합합니다.</p>
<div class="cards">{cards}</div>
<div class="scroll"><table>
<thead><tr><th>surface</th><th>status</th><th>evidence</th><th>decision</th></tr></thead>
<tbody>{rows}</tbody>
</table></div>
<h2>Next Frontier</h2>
<ul>{frontier}</ul>
"""


def main() -> None:
    data = build()
    OUT.mkdir(exist_ok=True)
    WEB.mkdir(exist_ok=True)
    (OUT / "map_animation_static_frontier_review.json").write_text(
        json.dumps(data, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    (WEB / "map_animation_static_frontier_review.html").write_text(
        render_html(data),
        encoding="utf-8",
    )
    print(
        "wrote map animation static frontier "
        f"(consumer={data['summary']['consumerGrounded']}, producer={data['summary']['promotedProducerCount']})"
    )


if __name__ == "__main__":
    main()
