#!/usr/bin/env python3
from pathlib import Path
import json, hashlib, sys
ROOT=Path(__file__).resolve().parents[2]
M=json.loads((ROOT/'config/nex_dynamic_warmup_frozen_player_manifest.json').read_text())
def sha(path):
    h=hashlib.sha256()
    with open(path,'rb') as f:
        for b in iter(lambda:f.read(1024*1024),b''): h.update(b)
    return h.hexdigest()
fail=[]
for group in ('lockedPresentationCore','lockedExerciseProfileHashes','motionAndModelHashes'):
    for rel,expected in M[group].items():
        p=ROOT/rel
        if not p.exists(): fail.append((group,rel,'MISSING',expected)); continue
        got=sha(p)
        if got!=expected: fail.append((group,rel,got,expected))
# Registry must be reproducible from profile files. Rebuild in memory and compare exact bytes.
# This detects hand-edits to generated registry without requiring it to be frozen.
pdir=ROOT/'assets/nex/workout_profiles/dynamic_warmup'
entries=[json.loads(p.read_text()) for p in sorted(pdir.glob('ex*.json'))]
tmpl="""(function(){\n  'use strict';\n  // GENERATED from assets/nex/workout_profiles/dynamic_warmup/ex*.json.\n  // Add/modify exercise profile data there; do not edit the frozen player core.\n  const entries = __ENTRIES__;\n  function deepFreeze(o){\n    if(!o || typeof o!=='object' || Object.isFrozen(o)) return o;\n    Object.freeze(o); Object.keys(o).forEach(k=>deepFreeze(o[k])); return o;\n  }\n  entries.forEach(deepFreeze);\n  function keyFor(step){ return String(step?.sequenceStepKey||step?.exerciseKey||step?.exercise||'').toLowerCase(); }\n  function resolve(step){\n    const key=keyFor(step);\n    const row=entries.find(e=>(e.matchKeys||[]).some(token=>key.includes(String(token).toLowerCase())));\n    return row?.profile || null;\n  }\n  window.NEXTDynamicWarmupTravelProfiles = deepFreeze({\n    schema:'NEXT11_DYNAMIC_WARMUP_TRAVEL_REGISTRY_V1',\n    version:'V425_APP_FROZEN_PLAYER_V6',\n    lockedThroughExercise:Math.max(0,...entries.filter(e=>e.locked).map(e=>Number(e.order)||0)),\n    entries, resolve\n  });\n})();\n""".replace('__ENTRIES__',json.dumps(entries,ensure_ascii=False,separators=(',',':')))
actual=(ROOT/'assets/js/data/nex-dynamic-warmup-travel-profiles.js').read_text()
if actual!=tmpl: fail.append(('generatedRegistry','assets/js/data/nex-dynamic-warmup-travel-profiles.js','DRIFT','REBUILD_REQUIRED'))
if fail:
    print('FROZEN PLAYER GUARD: FAIL')
    for row in fail: print(' | '.join(map(str,row)))
    sys.exit(1)
print(f"FROZEN PLAYER GUARD: PASS | core={len(M['lockedPresentationCore'])} | profiles_locked={len(M['lockedExerciseProfileHashes'])} | motion/model={len(M['motionAndModelHashes'])}")
