"""Replay recorded FP16 results against their exact recorded pixels, no inference."""
import json
import os
from pathlib import Path
import time
from unittest.mock import Mock
import uuid

import numpy as np
from PIL import ImageDraw
from app.byte_tracking import ByteTracker
from app.contracts.frames import FrameEnvelope
from app.det_result_path import DetResultPath
from app.frame_ingress import FrameIngress
from app.intrusion import Intrusion, IntrusionConfig
from app.metadata_render import render
from app.native_metadata import NativeFrame, NativeDetection
from app.stream_settings import revision

os.umask(0o077)
root = Path('/evidence')
old = Path('/recorded')
output = root/'replay'
output.mkdir(mode=0o700)
cfg = IntrusionConfig(enabled=True, roi=((.2, .2), (.8, .2), (.8, .95), (.2, .95)))
run = 'offline-replay-'+uuid.uuid4().hex
ingress = FrameIngress('replay-only', 'replay-only', 'replay-only', run, 1)
path = DetResultPath(ingress, ByteTracker(), 'RFDETRMedium', .5, Mock(), lambda: True,
                     Mock(), display_threshold=.25, intrusion=Intrusion(cfg),
                     scenario_revision=revision({'intrusion': cfg.payload()}))
path.start()
saved = []
event_count = 0
first_event = None
try:
    with (old/'frames.rgb').open('rb') as pixels, (old/'fp16.jsonl').open() as lines:
        for index, line in enumerate(lines):
            if index >= 60:
                break
            row = json.loads(line)
            assert row['frame'] == index
            raw = pixels.read(1280*720*3)
            assert len(raw) == 1280*720*3
            frame = FrameEnvelope('replay-only', 'replay-only', 'replay-only', run, 1, index,
                                  round(row['source_time_s']*1e9), time.time_ns()//1000000,
                                  1280, 720)
            detections = []
            for cls, score, x, y, w, h in row['detections']:
                box = tuple(max(0., min(1., v)) for v in (x/1280, y/720, (x+w)/1280, (y+h)/720))
                detections.append(NativeDetection(int(cls), score, box))
            path.submit(frame, NativeFrame(index, frame.pts_ns, 1280, 720, tuple(detections), 576, 576))
            until = time.monotonic()+2
            while path.status().get('processed', 0) < index+1 and time.monotonic() < until:
                time.sleep(.005)
            assert path.status().get('processed') == index+1, 'Replay result failed'
            result = path.latest_result()
            assert result.frame == frame
            event_count += len(result.events)
            event_sample = bool(result.events) and first_event is None
            if event_sample:
                first_event = index
            if index == 0 or event_sample or index == 59:
                if len(saved) >= 3:
                    continue
                bgr = np.frombuffer(raw, np.uint8).reshape(720, 1280, 3)[:, :, ::-1]
                image, _ = render(result, bgr, display_threshold=.25)
                draw = ImageDraw.Draw(image)
                draw.rectangle((0, 0, image.width, 31), fill='#16181A')
                draw.text((10, 8), f'OFFLINE RESULT REPLAY / NOT LIVE SDK / Frame {index}', fill='white')
                image.save(output/f'frame-{index}.jpg', quality=90)
                (output/f'frame-{index}.json').write_text(json.dumps(result.snapshot(), indent=2))
                saved.append(index)
finally:
    path.close(2)
    assert not path._thread.is_alive()
summary = dict(scope='recorded_frame_result_replay_not_live_sdk', frames=60,
               events_created=event_count, first_event_frame=first_event, samples=saved,
               threshold=.5, generic_display=.25, cleanup=True,
               model_inference=0, redis_connections=0, source_runtime=0)
(root/'replay-summary.json').write_text(json.dumps(summary, indent=2))
print(json.dumps(summary))
