import hashlib
import json
import os
from pathlib import Path
import statistics
import time
from inputs import OUT,load,annotations
from geometry import Spatial,Geometry
from motion import pair_features

clip=os.environ['CLIP'];dest=OUT/'work'/clip;dest.mkdir(parents=True,exist_ok=True)
complete=dest/'features_summary.json'
if complete.exists():
    summary=json.loads(complete.read_text())
    assert hashlib.sha256((dest/'features.jsonl').read_bytes()).hexdigest()==summary['sha256']
    print('REUSED',clip);raise SystemExit(0)
rows,chosen,spec,cache,maps=load(clip);refs=annotations(clip,rows,maps)
engine=Spatial();times=[];valid=0;candidate=0
with (dest/'features.jsonl').open('w') as output:
    for row in rows:
        start=time.perf_counter();v=engine.step(row)
        for pair in v['pairs']:
            pair['features'],pair['feature_rejections']=pair_features(pair,row['seconds'])
            pair.pop('history');pair['orders']=[b['order'] for b in pair['bodies']]
            pair['refs']=[b['ref'] for b in pair['bodies']]
        elapsed=(time.perf_counter()-start)*1000;times.append(elapsed)
        current=dict(sample=row['sample'],source_frame=row['source_frame'],seconds=row['seconds'],
            width=row['width'],height=row['height'],displayed=row['sample'] in chosen,**v,**refs[row['sample']])
        if current['displayed']:
            valid+=any(p['features'] for p in v['pairs']);candidate+=bool(v['pairs'])
        output.write(json.dumps(current,separators=(',',':'))+'\n')
summary=dict(status='PASS',clip=clip,processed=len(rows),displayed=len(chosen),
    observable_frames=valid,candidate_frames=candidate,settings=Geometry().payload(),
    cache_sha256=spec['cache_sha256'],causal=True,GPU=False,
    feature_p95_ms=statistics.quantiles(times,n=100,method='inclusive')[94],feature_max_ms=max(times),
    sha256=hashlib.sha256((dest/'features.jsonl').read_bytes()).hexdigest())
complete.write_text(json.dumps(summary,indent=2));print(json.dumps(summary),flush=True)
