import csv
import json
from pathlib import Path

R=Path(__file__).parent
all_rows=[]; report={}
for name in ('three','two','restored'):
    if not (R/(name+'.json')).exists():continue
    d=json.loads((R/(name+'.json')).read_text()); sums=json.loads((R/(name+'-summary.json')).read_text())
    a,b=d['resources']; dt=b['at']-a['at']
    threads=[]
    for k,v in b['threads'].items():
        old=a['threads'].get(k)
        if old and old['start']==v['start']:
            threads.append(dict(tid=k,comm=v['comm'],cpu_percent=100*(v['ticks']-old['ticks'])/a['ticks_per_second']/dt,runqueue_wait_ms=(v['runqueue_wait_ns']-old['runqueue_wait_ns'])/1e6))
    result=dict(cpu_cores=(b['cpu']['usage_usec']-a['cpu']['usage_usec'])/1e6/dt,
                throttle_delta=b['cpu']['throttled_usec']-a['cpu']['throttled_usec'],
                memory_mib=[a['memory']/1024**2,b['memory']/1024**2],gpu=[a['gpu'],b['gpu']],
                top_threads=sorted(threads,key=lambda t:t['cpu_percent'],reverse=True)[:10],channels={})
    queues=[x['publisher']['metrics']['queued'] for x in d['samples']]
    result['publisher_queue_range']=[min(queues),max(queues)]
    for source,s in sums.items():
        samples=[]
        for q in s['profiles']:
            classes=q['classes']
            samples.append(dict(wait_ms=q['kernel_wait_ms'],compute_wall_ms=q['wall_ms'],compute_cpu_ms=q['thread_cpu_ms'],candidates=sum(c['candidates'] for c in classes),active_classes=sum(not c['fast_path'] for c in classes),tracks=[sum(c['before'][i] for c in classes) for i in range(3)]))
        frames=[x['channels'][source]['redis']['frame'] for x in d['samples']]
        states=[x['channels'][source]['state'] for x in d['samples']]
        perf0=states[0]['metadata_path']['performance'];perf1=states[-1]['metadata_path']['performance']
        rtp=[f.get('frameTime',{}).get('rtpTimestamp') for f in frames]
        row=dict(window=name,channel=source[-2:],seconds=s['seconds'],decoded_fps=s['fps'].get('decoded'),selected_fps=s['fps'].get('selected'),infer_fps=s['fps'].get('infer'),native_fps=s['fps'].get('native'),result_fps=s['fps'].get('result'),redis_fps=s['redis_fps'],queue_first=s['queue'][0],queue_last=s['queue'][-1],queue_min=min(s['queue']),queue_max=max(s['queue']),stale_delta=s['counter_delta'].get('stale',0),capacity_drop_delta=s['counter_delta'].get('queue_drop',0),tracking_mean_ms=s['durations']['tracking']['mean_ms'],tracking_p95_ms=s['durations']['tracking']['p95_ms'],tracking_thread_cpu_ms=s['durations']['tracking_cpu']['mean_ms'],scenario_mean_ms=s['durations']['scenario']['mean_ms'],observation_missed_delta=perf1['observation_missed']-perf0['observation_missed'])
        all_rows.append(row)
        result['channels'][source[-2:]]=dict(summary=row,sparse_profiles=samples,shape=s['shapes'],frameSeq=[frames[0].get('frameSeq'),frames[-1].get('frameSeq')],rtp=[rtp[0],rtp[-1]],rtp_present=all(v is not None for v in rtp),objects_range=[min(len(f['objects']) for f in frames),max(len(f['objects']) for f in frames)],redis_length_range=[min(x['channels'][source]['redis']['length'] for x in d['samples']),max(x['channels'][source]['redis']['length'] for x in d['samples'])],ttl=s['ttl'],errors=[x.get('last_error') for x in states if x.get('last_error')])
    report[name]=result
(R/'analysis.json').write_text(json.dumps(report,indent=2))
with (R/'comparison.csv').open('w') as f:
    w=csv.DictWriter(f,fieldnames=list(all_rows[0]));w.writeheader();w.writerows(all_rows)
print(json.dumps(report,indent=2))
