"""Pair the original Activities influence producer, independent of jump links."""
import hashlib,importlib.util,json,struct
from pathlib import Path
sp=importlib.util.spec_from_file_location('audit',Path(__file__).with_name('Audit-GalaxyClientCompatibility.py'))
a=importlib.util.module_from_spec(sp);sp.loader.exec_module(a)
old=a.Image(Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe'))
new=a.Image(Path('D:/SteamLibrary/steamapps/common/Elite Dangerous/Products/elite-dangerous-odyssey-64/EliteDangerous64.exe'))
hashes=[hashlib.sha256(im.raw).hexdigest() for im in (old,new)]
assert hashes==['6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93','ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63']
functions=[];refs=[]
for before in [0x3AE7600,0x3B27630,0x3ACF250,0x3AF6C40,0x3B3E5B0,0x1418810,0x3ACA1A0]:
    span=old.function(before);assert span and span[0]==before
    row=a.match(old,new,before,span[1]-before);assert row['status']=='unique',row
    row['oldRva']=hex(before);functions.append(row)
    refs+=a.references(old,new,before,int(row['newRva'],16),row['length'])
def paired(before):
    values={r[1] for r in refs if r[0]==before};assert len(values)==1,(hex(before),values)
    return values.pop()
table=paired(0x552E5C8);slots=[]
for slot,before in [(0x20,0x3B3E5B0),(0x40,0x3AF6C40),(0x68,0x3B27630)]:
    after=int(next(r['newRva'] for r in functions if int(r['oldRva'],16)==before),16)
    assert struct.unpack('<Q',old.data(0x552E5C8+slot,8))[0]-old.base==before
    assert struct.unpack('<Q',new.data(table+slot,8))[0]-new.base==after
    slots.append(dict(oldVtable=hex(0x552E5C8),newVtable=hex(table),slot=hex(slot),oldRva=hex(before),newRva=hex(after)))
phase_scale=paired(0x4DE28B4)
old_scale=struct.unpack('<f',old.data(0x4DE28B4,4))[0]
assert struct.unpack('<f',new.data(phase_scale,4))[0]==old_scale
folder=Path('artifacts/galaxy-query-research/power-influence');folder.mkdir(exist_ok=True)
result=dict(sourceHashes=hashes,functions=functions,slots=slots,vtables={hex(0x552E5C8):hex(table)},globals={hex(0x4DE28B4):hex(phase_scale)},
    phaseScale=old_scale,recordStride=64,
    contract='Only source-ready Activities centre/candidate pairs, exactly one nonzero source extent, strict distance<extent, and other state0 or equal original owner index. Extent owner supplies original linear RGB; buffer kind and deterministic candidate-address phase remain separate from jump connections.',
    gameProcessAccess=False,gameCalls=0,runtimeValidated=False)
(folder/'compatibility.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(dict(functions=len(functions),vtable=hex(table),phaseScale=old_scale)))
