import json
import subprocess
import time

from process_ops import R, p, rt, previous, REPO

states = rt.states()
result = p.read('final.json')
assert result['success']
image = p.read('image2.json')
assert all(p.sha(REPO / name) == sha for name, sha in image['hashes'].items())
pids = [states[s]['child_pid'] for s in rt.ORIGINAL]
old_pid = p.read('actual-lifecycle.json')['old_pid']
code = '''
import hashlib,json,os,sys
from pathlib import Path
pids=json.loads(sys.argv[1]);old=int(sys.argv[2]);hashes=json.loads(sys.argv[3])
assert not Path('/proc/'+str(old)).exists()
out=[]
for pid in pids:
    root=Path('/proc/'+str(pid));status=dict(line.split(':',1) for line in (root/'status').read_text().splitlines())
    maps=(root/'maps').read_text()
    out.append(dict(pid=pid,parent=int(status['PPid']),cwd=os.readlink(root/'cwd'),
        sdk_loaded='libnvds' in maps,threads=int(status['Threads']),rss_kib=int(status['VmRSS'].split()[0])))
assert len({v['pid'] for v in out})==3 and len({v['parent'] for v in out})==1
parent=out[0]['parent'];maps=Path('/proc/'+str(parent)+'/maps').read_text()
for name,digest in hashes.items():
    if name.startswith(('app/','docker/')):
        path=Path('/usr/local/bin/entrypoint.sh') if name=='docker/entrypoint.sh' else Path('/opt/contextra',name)
        assert hashlib.sha256(path.read_bytes()).hexdigest()==digest,name
assert all(v['sdk_loaded'] for v in out)
assert 'libnvds' not in maps
print(json.dumps(dict(children=out,parent_pid=parent,parent_sdk_loaded=False,old_child_gone=True,
    source_hashes_match=True,python=sys.version.split()[0])))
'''
run = subprocess.run(['docker','exec','contextra-analytics-1','python3','-c',code,
    json.dumps(pids),str(old_pid),json.dumps(image['hashes'])],capture_output=True,text=True,timeout=10)
assert run.returncode == 0,run.stderr
ownership = json.loads(run.stdout)
samples = {}
for row in previous.previous.ROWS:
    sid = row['stream_id']
    q = states[sid]
    assert q['state'] == 'running' and q['last_error'] is None and q['cleanup_error'] is None
    assert not q['metadata_path']['performance']['detail']
    samples[sid] = rt.redis_sample(row,frame=True)
p.save('metadata-readback.json',samples)
p.save('runtime-ownership.json',ownership)
window=p.read('window.json')['samples']
resources=[v['resource'] for v in window]
cpu=[(b['cpu']['usage_usec']-a['cpu']['usage_usec'])/1e6/(b['at']-a['at']) for a,b in zip(resources,resources[1:])]
summary=dict(samples=len(resources),memory_gib=[min(v['memory'] for v in resources)/1024**3,max(v['memory'] for v in resources)/1024**3],
    cpu_cores=[min(cpu),max(cpu)],gpu_util=[min(v['gpu'][0][2] for v in resources),max(v['gpu'][0][2] for v in resources)],
    gpu_mib=[min(v['gpu'][0][0] for v in resources),max(v['gpu'][0][0] for v in resources)],
    available_ram_gib=min(v['available'] for v in resources)/1024**3,disk_free_gib=min(v['disk'] for v in resources)/1024**3,
    cpu_throttled_delta=resources[-1]['cpu']['throttled_usec']-resources[0]['cpu']['throttled_usec'],
    publisher=rt.api('/api/v1/metadata/status')['metrics'],observed_seconds=window[-1]['at']-window[0]['at'])
p.save('resource-summary.json',summary)
p.save('readback.json',dict(at=time.time(),success=True,child_pids=pids,source_hashes_match=True,diagnostics_off=True,
    fixture_removed=not subprocess.check_output(['docker','ps','-aq','--filter','name=codex-channel-process-redis-20260916'],text=True).strip()))
print(json.dumps(dict(ownership=ownership,resource=summary),indent=2))
