import hashlib
import json
from pathlib import Path
import sys

OUT=Path('/out')
RB='/storage/contextra/experiments/action-model-eval/2026'
sys.path.insert(0,'/opt/contextra')


def read(path):return json.loads(Path(path).read_text())


def sha(path):
    h=hashlib.sha256()
    with Path(path).open('rb') as f:
        for b in iter(lambda:f.read(1024*1024),b''):h.update(b)
    return h.hexdigest()


def save(path,value):
    path=Path(path);path.parent.mkdir(parents=True,exist_ok=True)
    assert not path.exists(),path
    path.write_text(json.dumps(value,ensure_ascii=False,indent=2,allow_nan=False))


def evidence(path):
    assert path.startswith(RB+'/'),path
    return Path('/evidence')/path[len(RB)+1:]


def load(clip):
    spec=read(OUT/'specs.json')[clip];cache=evidence(spec['cache'])/'inputs'
    assert sha(cache/'pose.json')==spec['cache_sha256']
    rows=read(cache/'pose.json');selected=set(spec['selected_samples'])
    assert all(r['sample']==i for i,r in enumerate(rows))
    assert all(b['seconds']>a['seconds'] and b['source_frame']>a['source_frame'] for a,b in zip(rows,rows[1:]))
    assert len([r for r in rows if r['sample'] in selected])==len(selected)
    mapping={int(x['sample']):x for x in read(OUT/'self_maps.json').get(clip,[])}
    for r in rows:
        if mapping:
            m=mapping[r['sample']]
            assert int(m['clip_frame_1based'])==r['source_frame'] and abs(float(m['clip_pts_seconds'])-r['seconds'])<1e-5
    return rows,selected,spec,cache,mapping


def annotation(clip,row,spec,mapping,cases,references):
    if spec['domain']=='self':
        m=mapping[row['sample']];review=int(m['review_frame_1based']);lo,hi=spec['core_review_range']
        active=[c for c in cases if any(l['clip_id']==spec['clip_id'] for l in c['links']) and
                c['review_anchor_range'][0]<=review<=c['review_anchor_range'][1]]
        return dict(reference='negative_reference',region='body' if lo<=review<=hi else 'context',
            review_frame=review,case_ids=[c['case_id'] for c in active],dedupe_key='SELF01:'+str(review),
            exact_gt=False)
    bounds=references['legacy'][clip];number=row['source_frame'];lo,hi=bounds['down']
    label='positive_reference' if number>=lo and (hi is None or number<=hi) else 'unlabelled'
    if 'fall_motion' in bounds and bounds['fall_motion'][0]<=number<=bounds['fall_motion'][1]:label='transition_reference'
    return dict(reference=label,region='approximate_user_anchor',review_frame=None,case_ids=[],
        dedupe_key=clip+':'+str(number),exact_gt=False)
