"""Bounded renderer diagnostics; no input payloads or authentication data."""
import json
import re
import threading
import time


class StderrTail:
    def __init__(self, pipe, limit=8192):
        self.pipe, self.limit, self.tail = pipe, limit, bytearray()
        self.thread = threading.Thread(target=self._read, name='artifact-stderr', daemon=True)
        self.thread.start()

    def _read(self):
        try:
            while data := self.pipe.read(4096):
                self.tail.extend(data)
                del self.tail[:-self.limit]
        finally:
            self.pipe.close()

    def finish(self):
        self.thread.join(2)
        if self.thread.is_alive():
            return 'STDERR_READER_INCOMPLETE'
        text = self.tail.decode('utf-8', errors='replace')
        text = re.sub(r'(?:rtsp[s]?|https?)://\S+', '<URL_REDACTED>', text)
        return re.sub(r'(?im)^.*(?:authorization|password|token|secret).*$','<SECRET_REDACTED>',text)


def save_diagnostic(stage, value):
    folder = stage/'ready' if (stage/'ready').is_dir() else stage
    folder.mkdir(parents=True, exist_ok=True)
    path = folder/'render-diagnostic.json'
    previous = json.loads(path.read_text()) if path.exists() else {}
    previous.update(value)
    path.write_text(json.dumps(previous, ensure_ascii=True, indent=2))


class RenderDiagnostic:
    def __init__(self):
        self.start = time.monotonic()
        self.phase = 'init'
        self.phase_at = self.start
        self.times = {}
        self.frames = 0

    def enter(self, phase):
        now = time.monotonic()
        self.times[self.phase] = self.times.get(self.phase, 0.) + now-self.phase_at
        self.phase, self.phase_at = phase, now

    def snapshot(self):
        now = time.monotonic()
        times = dict(self.times)
        times[self.phase] = times.get(self.phase, 0.) + now-self.phase_at
        return dict(phase=self.phase, elapsed_seconds=now-self.start,
                    phase_seconds=times, selected_frames=self.frames)
