"""Freeze user-provided inclusive ranges against preserved recording evidence."""
import csv
import datetime
import hashlib
import json
import pathlib
from zoneinfo import ZoneInfo

ROOT = pathlib.Path(__file__).resolve().parent.parent
BASE = ROOT.parent
RANGES = [
    (6, 'fall', '쓰러짐', 362, 722), (6, 'crowd', '군중', 723, 1083),
    (8, 'segment', '지정 구간', 112, 472), (9, 'segment', '지정 구간', 242, 482),
    (10, 'fall', '쓰러짐', 242, 602), (10, 'intrusion', '침입', 603, 843),
    (11, 'crowd', '군중', 362, 602), (11, 'fall', '쓰러짐', 603, 963),
    (14, 'fight', '싸움', 242, 482),
    (15, 'fall', '쓰러짐', 362, 722), (15, 'fire', '화재', 723, 1083),
    (16, 'fall', '쓰러짐', 353, 713),
    (18, 'crowd', '군중', 112, 352), (18, 'fall', '쓰러짐', 353, 713),
    (19, 'fire', '화재', 112, 472), (19, 'fall', '쓰러짐', 473, 833),
    (20, 'fall', '쓰러짐', 242, 602), (20, 'crowd', '군중', 603, 843),
    (21, 'fire', '화재', 112, 352), (21, 'fall', '쓰러짐', 353, 713),
]

def digest(path):
    h = hashlib.sha256()
    with path.open('rb') as f:
        for chunk in iter(lambda: f.read(1048576), b''):
            h.update(chunk)
    return h.hexdigest()

def main():
    sources = {}
    clips = []
    for cid in sorted({x[0] for x in RANGES}):
        run = '2026-11-02_contextra-' + ('approved16-recordings_r01' if cid < 18 else 'retry7-recordings_r01')
        source = BASE / run / f'camera{cid}'
        metadata = json.loads((BASE / run / 'manifest.json').read_text())
        name = next(x['name'] for x in metadata['targets'] if x['camera_id'] == cid)
        check = json.loads((source / 'reports/video_validation.json').read_text())
        video = source / f'inputs/camera{cid}_original.mp4'
        mapping = source / f'inputs/camera{cid}_frame_map.csv'
        assert digest(video) == check[video.name]['sha256']
        assert digest(mapping) == check[mapping.name]['sha256']
        with mapping.open() as f:
            rows = list(csv.DictReader(f))
        assert [int(x['frame_1based']) for x in rows] == list(range(1, check['frame_count'] + 1))
        sources[str(cid)] = dict(camera_id=cid, name=name, run=run, frames=len(rows), source_sha256=check[video.name]['sha256'], source_map_sha256=check[mapping.name]['sha256'])
        for j, (_, kind, label, first, last) in enumerate([x for x in RANGES if x[0] == cid], 1):
            assert 1 <= first <= last <= len(rows)
            clips.append(dict(id=f'camera{cid:02d}_{j:02d}_{kind}_F{first:04d}-{last:04d}', camera_id=cid, name=name, case_label=label, label_origin='user_range_annotation' if kind != 'segment' else 'unspecified_by_user', first=first, last=last, frames=last-first+1, first_recording_pts=rows[first-1]['original_pts_seconds'], last_recording_pts=rows[last-1]['original_pts_seconds']))
    assert len(clips) == 20 and sum(x['frames'] for x in clips) == 6380
    manifest = dict(created_at=datetime.datetime.now(ZoneInfo('Asia/Seoul')).isoformat(), numbering='source decoded 1-based; inclusive start and end', clips=clips, sources=sources, excluded={'camera7':'user stated same as camera27','camera14_fire':'user stated same as camera29','camera16_crowd':'user stated same as camera22','camera12_13_17':'deferred capture failures'}, note='camera11 second segment is user-labeled fall despite source name Intrusion; camera8/9 remain unspecified segment labels', policy={'no_context_added':True,'no_new_recording':True,'no_inference':True,'no_resampling':True,'preserve_sources':True})
    with (ROOT/'manifest.json').open('x') as f:
        json.dump(manifest,f,ensure_ascii=False,indent=2)
    print(json.dumps({'clips':len(clips),'channels':len(sources),'selected_frames':6380}))

if __name__ == '__main__':
    main()
