import csv
import hashlib
import importlib.util
import json
from pathlib import Path
import yaml

R=Path(__file__).parent
s=importlib.util.spec_from_file_location('ops',R/'ops.py');o=importlib.util.module_from_spec(s);s.loader.exec_module(o);p=o.p
plan=p.read('plan.json');build=p.read('fixed-build.json');rows=[];diagnostics={};resources={}
for label in ['baseline','probe','fixed']:
    data=p.read(label+'-window.json');summary=p.read(label+'-window-summary.json')
    pub=p.read(label+'-publisher.json')['metrics'];a,b=data['samples'][0]['publisher']['metrics'],data['samples'][-1]['publisher']['metrics']
    resources[label]=dict(publisher_delta={k:b.get(k,0)-a.get(k,0) for k in ['sent_frames','sent_status','replaced','expired','send_error','byte_limit','message_limit']},publisher_queue_range=[min(x['publisher']['metrics']['queued'] for x in data['samples']),max(x['publisher']['metrics']['queued'] for x in data['samples'])])
    ra,rb=data['resources'];dt=rb['at']-ra['at']
    resources[label].update(cpu_cores=(rb['cpu']['usage_usec']-ra['cpu']['usage_usec'])/1e6/dt,memory_mib=[ra['memory']/1024**2,rb['memory']/1024**2],gpu=[ra['gpu'],rb['gpu']],throttle_delta=rb['cpu']['throttled_usec']-ra['cpu']['throttled_usec'])
    for src,v in summary.items():
        key=hashlib.sha256(src.encode()).hexdigest();profile=pub.get('profile',{}).get('channels',{}).get(key,{})
        diagnostics[label+src[-2:]]=profile
        row=dict(condition=label,channel=src[-2:],seconds=v['seconds'],result_fps=v['fps']['result'],submit_fps=v['fps']['publisher_submit'],redis_fps=v['redis_fps'],result_queue_min=min(v['queue']),result_queue_max=max(v['queue']),stale_delta=v['counter_delta'].get('stale',0),queue_drop_delta=v['counter_delta'].get('queue_drop',0),profile_state_replaced=profile.get('counts',{}).get('replaced_by_state','unmeasured' if label=='baseline' else 0),profile_frame_replaced=profile.get('counts',{}).get('replaced_by_frame','unmeasured' if label=='baseline' else 0))
        rows.append(row)
with (R/'comparison.csv').open('w') as f:
    writer=csv.DictWriter(f,fieldnames=list(rows[0]));writer.writeheader();writer.writerows(rows)
cur=p.base.inspect('contextra-analytics-1');assert cur['Image']==build['image'] and cur['State']['Health']['Status']=='healthy'
assert dict(x.split('=',1) for x in cur['Config']['Env'])==dict(x.split('=',1) for x in plan['analytics']['Config']['Env'])
assert sorted(cur['Mounts'],key=lambda x:x['Destination'])==sorted(plan['analytics']['Mounts'],key=lambda x:x['Destination'])
assert cur['HostConfig']['RestartPolicy']==plan['analytics']['HostConfig']['RestartPolicy']
assert p.sha(p.prior.REG)==plan['registry_hash']
assert yaml.safe_load(p.ACTIVE.read_text())['services']['analytics']['image']==build['image']
assert 'CONTEXTRA_IMAGE='+build['tag'] in p.ENV.read_text().splitlines()
assert p.base.inspect('contextra-redis-1')['Id']==plan['redis']
assert p.prior.ops.prior.prev.sender()['executionId']==plan['sender']['executionId']
inv=p.base.inventory();assert {k:v for k,v in inv.items() if k!='/contextra-analytics-1'}=={k:v for k,v in plan['inventory'].items() if k!='/contextra-analytics-1'}
states={src:p.prior.state(sid) for src,sid in p.CHANNELS.items()}
for src,sid in p.CHANNELS.items():
    assert states[src]['state']=='running' and states[src]['last_error'] is None and states[src]['cleanup_error'] is None
    assert not states[src]['metadata_path']['performance']['detail'] and states[src]['metadata_path']['visual'] is None
    assert p.api('/api/v1/streams/'+sid+'/settings')['configured']==plan['settings'][src]['configured']
assert not p.api('/api/v1/metadata/status')['metrics']['profile']['enabled']
cleanup={}
for label in ['probe','fixed']:
    cleanup[label]={sid:p.read(label+'-'+sid+'-cleanup.json')['last_cleanup'] for sid in p.CHANNELS.values()}
p.save('final.json',dict(rows=rows,diagnostics=diagnostics,resources=resources,states=states,cleanup=cleanup,build=build,config_preserved=True,others_preserved=True,persistent_image_aligned=True,metrics_off=True))
print(json.dumps(dict(rows=rows,resources=resources,states={s:q['state'] for s,q in states.items()},cleanup=cleanup)))
