"""Source/cache provenance and selected-frame correspondence, no semantic review."""
import hashlib
import json
import os
import pathlib
import av
import numpy as np
from PIL import Image

CLIP=os.environ['CLIP'];ROOT=pathlib.Path('/eval');CACHE=pathlib.Path('/cache')
spec=json.loads(pathlib.Path('/specs.json').read_text())[CLIP]
reference=json.loads(pathlib.Path('/model_reference.json').read_text())['pose']
summary=json.loads((CACHE/'reports/pose_summary.json').read_text())
assert summary['status']=='PASS'
for key in ('fps','person_threshold','nms_iou','tracking','preprocess','model','engine_sha256','source_files'):
    assert summary[key]==reference[key],(CLIP,key)
raw=(CACHE/'inputs/pose.json').read_bytes();rows=json.loads(raw)
assert len(rows)==summary['samples']
for i,r in enumerate(rows):
    assert r['sample']==i and r['source_frame']>=1 and np.isfinite(r['seconds'])
    if i:assert r['seconds']>rows[i-1]['seconds'] and r['source_frame']>rows[i-1]['source_frame']
    ids=[p['track_id'] for p in r['persons'] if p['track_id'] is not None]
    assert len(ids)==len(set(ids)) and len({p['query'] for p in r['persons']})==len(r['persons'])
    for p in r['persons']:
        assert p['score']>=.15 and len(p['keypoints'])==17 and len(p['bbox'])==4
        assert p['track_id'] is None or (type(p['track_id']) is int and p['track_id']>0)
bounds=spec['display_bounds'];selected=[r for r in rows if bounds is None or bounds[0]<=r['source_frame']<=bounds[1]]
assert selected
assert hashlib.sha256(pathlib.Path('/source.mp4').read_bytes()).hexdigest()==spec['sha256']
targets={r['source_frame']:r for r in selected};checks={selected[i]['source_frame'] for i in (0,len(selected)//2,len(selected)-1)}
rgb_checks=[];matched=0
with av.open('/source.mp4') as source:
    stream=source.streams.video[0];stream.codec_context.thread_count=2
    probe=dict(width=stream.width,height=stream.height,average_rate=str(stream.average_rate),declared_frames=stream.frames,codec=stream.codec_context.name)
    first_pts=None
    for n,frame in enumerate(source.decode(video=0),1):
        assert not frame.is_corrupt and frame.pts is not None
        pts=float(frame.pts*frame.time_base)
        if first_pts is None:first_pts=pts
        if n in targets:
            r=targets[n];assert (frame.width,frame.height)==(r['width'],r['height'])
            assert abs((pts-first_pts)-r['seconds'])<1e-6,(n,pts,r['seconds'])
            matched+=1
            if n in checks:
                with Image.open(CACHE/'inputs/frames'/f"{r['sample']:04d}.png") as saved:
                    a=np.asarray(saved.convert('RGB')).astype(np.int16)
                b=frame.to_ndarray(format='rgb24').astype(np.int16)
                delta=np.abs(a-b);mae=float(delta.mean());maximum=int(delta.max())
                assert maximum<=1 and mae<.1,(CLIP,n,mae,maximum)
                rgb_checks.append(dict(source_frame=n,mean_absolute_error=mae,max_error=maximum))
        if n>=selected[-1]['source_frame']:break
assert matched==len(selected)
data=dict(status='PASS',clip=CLIP,reused=spec['reused'],source_sha256=spec['sha256'],
          cache_sha256=hashlib.sha256(raw).hexdigest(),pose_summary_sha256=hashlib.sha256((CACHE/'reports/pose_summary.json').read_bytes()).hexdigest(),
          source_probe=probe,selected_samples=[r['sample'] for r in selected],observations=len(selected),cache_observations=len(rows),
          first_source_frame=selected[0]['source_frame'],last_source_frame=selected[-1]['source_frame'],
          first_seconds=selected[0]['seconds'],last_seconds=selected[-1]['seconds'],rgb_checks=rgb_checks,
          max_display=max(sum(p['score']>=.25 for p in r['persons']) for r in selected),
          cache_limit='derived people >=0.15 after parse>=0.1 and NMS0.85; all 17 original joint scores retained',
          prefilter_candidates_available=(CACHE/'inputs/pose_candidates_prefilter.jsonl').is_file())
(ROOT/'reports/cache_validation.json').write_text(json.dumps(data,indent=2))
print(json.dumps(data),flush=True)
