"""Bounded local signed-resource prefixes; no process reads or game invocation."""
import concurrent.futures,hashlib,importlib.util,json,re,sys,time
from pathlib import Path

spec=importlib.util.spec_from_file_location('assets',Path(__file__).with_name('galaxy_asset_inventory.py'))
saved=sys.argv;sys.argv=['inventory','artifacts/galaxy-query-research/power-outer-sources/unused.json']
assets=importlib.util.module_from_spec(spec);spec.loader.exec_module(assets);sys.argv=saved
index=json.loads(Path('artifacts/galaxy-query-research/palette-resources/signed-metadata.json').read_text())
keys=[r['key'] for r in index['headers'] if r['strings'][1:2]==[':tex'] and 'FGDK:FragmentMaterial:fgm' in r['strings']]
if len(keys)!=5247:raise ValueError('Bounded candidate inventory changed')
pattern=re.compile(rb'spectralclass|milkywaydust|simplebillboardglow|simpleannulus|galaxymapresources|focusring',re.I)
def scan(key):
    path=assets.ROOT/('0'+key[0])/key
    raw=assets.decode(path,262+8192)
    if not pattern.search(raw):return None
    strings=[m.group().decode() for m in re.finditer(rb'[A-Za-z_][A-Za-z0-9_.:/ -]{3,}',raw)]
    return dict(resource=key,sourceBytes=path.stat().st_size,decodedPrefixSha256=hashlib.sha256(raw).hexdigest(),strings=strings[:120])
start=time.monotonic();matches=[];count=0
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    for row in executor.map(scan,keys):
        count+=1
        if row:matches.append(row)
result=dict(processAccess=False,gameCalls=0,candidates=count,prefixBytes=8192,workers=2,seconds=time.monotonic()-start,matches=matches)
Path('artifacts/galaxy-query-research/power-outer-sources/material-prefix-matches.json').write_text(json.dumps(result,indent=2))
print(json.dumps(result,indent=2))
