from pathlib import Path
import json,subprocess,tempfile,os
import lupa.luajit21 as lj
R=Path(__file__).resolve().parents[1]
def lua(L,v):
 if isinstance(v,dict):return L.table_from({k:lua(L,x)for k,x in v.items()})
 if isinstance(v,list):return L.table_from([lua(L,x)for x in v])
 return v
def py(v):
 if hasattr(v,'items'):
  d={k:py(x)for k,x in v.items()}
  return [d[i]for i in range(1,len(d)+1)]if d and set(d)==set(range(1,len(d)+1))else d
 return v
with tempfile.TemporaryDirectory()as tmp:
 so=Path(tmp)/'lightfixture.so'
 subprocess.run(['gcc','-shared','-fPIC',str(R/'tests/lightfixture.c'),str(Path(lj.__file__)), '-Wl,-rpath,'+str(Path(lj.__file__).parent),'-o',str(so)],check=True)
 variants=[('EXO-45','79e4b3d2da5e45e3','824b7e0c4c879eb5','08f6089289c83d22'),('EXO-49','c2d449ecf7facab1','e5f64dcc3bfe9dd1','ff9878576a4c543b'),('EXO-51','7b2326f6fd9c8069','0736bee2d6328726','17c5d12d8d5dee2c'),('EXO-55','35dbf54f016f3624','65489809a8181b96','df51fe8d62f294be')]
 runs=[]
 for label,body,left,right in variants:
  L=lj.LuaRuntime(unpack_returned_tuples=True);L.globals().SOURCE=str(R/'src');L.globals().LIGHT_LIBRARY=str(so)
  fixture=json.loads((R/'tests/three-mechs-identities.json').read_text())
  for d in fixture['mechs']:d['resource']=body
  for i,d in enumerate(fixture['arms']):d['resource']=left if i%2==0 else right
  L.globals().FIXTURE=lua(L,fixture)
  L.globals().LIVE_API=lua(L,json.loads((R/'tests/live-api-t1-failure.json').read_text())['api_functions'])
  root=Path(tmp)/label;os.environ['APPDATA']=str(root);(root/'Arrowhead/Helldivers2').mkdir(parents=True)
  prefix=(R/'tests/test_spatial.lua').read_text().split("local runtime=load('spatial_runtime')(sr,N,Z,policy)")[0]
  setup=(R/'tests/tagged_bridge_spec.lua').read_text().split("local Ref=factory(sr);local runtime=")[0]
  result=py(L.execute(prefix+setup+(R/'tests/mount_runtime_spec.lua').read_text()));result['model']=label
  reports=list((root/'Arrowhead/Helldivers2').glob('*.json'));assert any('MOUNT_POINT_TEST'in p.read_text()and 'match_method'in p.read_text()for p in reports)
  result['mount_mode_in_hud_json_report']=True;runs.append(result)
 report={'checks':sum(x['checks']for x in runs),'model_runs':runs,'cases_per_model':len(runs[0]['cases']),'variant_resources_synthetic':True,'fixture_note':'Reuse recorded EXO-51 descriptor numbers with synthetic resource substitutions; all positions/HP/native graphs are mocked. Not four real game captures.'}
 L2=lj.LuaRuntime(unpack_returned_tuples=True);config=L2.execute((R/'src/config.lua').read_text())
 assert config(tmp+'/')['mount_match'] is True
 (Path(tmp)/'mech_hud.cfg').write_text('mount_match=false\nspatial=true\n')
 assert config(tmp+'/')['mount_match'] is False
 report['config_default_and_disable_verified']=True
report.update({'genuine_lua_lightuserdata':True,'real_luajit_ffi_conversion':True,'engine_and_health_mocked':True,'real_game_calls':0,'live_hd2_encoding_confirmed':False,'multiplayer_fix_live_verified':False})
(R/'validation/mount-runtime-tests.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n');print(json.dumps(report,ensure_ascii=False,indent=2))
