// offscreen-record.js — runs MediaRecorder (not available in the MV3 service worker).
// The SW hands us a tabCapture streamId; we record to WebM and return it as base64 on stop.

let recorder = null;
let chunks = [];
let mime = 'video/webm';

chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
  if (!msg || msg.target !== 'offscreen-record') return;
  if (msg.action === 'start') { start(msg).then(sendResponse).catch((e) => sendResponse({ ok: false, error: String((e && e.message) || e) })); return true; }
  if (msg.action === 'stop') { stop().then(sendResponse).catch((e) => sendResponse({ ok: false, error: String((e && e.message) || e) })); return true; }
});

async function start(msg) {
  const src = msg.source === 'desktop' ? 'desktop' : 'tab'; // desktopCapture vs legacy tabCapture
  const fps = Number(msg.fps) || 30;
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: msg.audio ? { mandatory: { chromeMediaSource: src, chromeMediaSourceId: msg.streamId } } : false,
    video: { mandatory: { chromeMediaSource: src, chromeMediaSourceId: msg.streamId, maxFrameRate: fps } },
  });
  chunks = [];
  // vp9 for quality/fps; fall back if unsupported
  mime = MediaRecorder.isTypeSupported('video/webm;codecs=vp9') ? 'video/webm;codecs=vp9' : 'video/webm';
  recorder = new MediaRecorder(stream, { mimeType: mime, videoBitsPerSecond: msg.bitrate || 6000000 });
  recorder.ondataavailable = (e) => { if (e.data && e.data.size) chunks.push(e.data); };
  // stop cleanly if the user ends the share from Chrome's "Stop sharing" bar
  stream.getVideoTracks()[0].addEventListener('ended', () => { try { if (recorder && recorder.state !== 'inactive') recorder.stop(); } catch (e) {} });
  recorder.start(1000); // 1s timeslices
  return { ok: true, mimeType: mime, fps };
}

function stop() {
  return new Promise((resolve) => {
    if (!recorder) return resolve({ ok: false, error: 'not recording' });
    recorder.onstop = async () => {
      try {
        const blob = new Blob(chunks, { type: mime });
        const buf = new Uint8Array(await blob.arrayBuffer());
        let bin = '';
        const CH = 0x8000;
        for (let i = 0; i < buf.length; i += CH) bin += String.fromCharCode.apply(null, buf.subarray(i, i + CH));
        const out = { ok: true, base64: btoa(bin), mimeType: mime, sizeKB: Math.round(buf.length / 1024) };
        recorder.stream.getTracks().forEach((t) => t.stop());
        recorder = null;
        chunks = [];
        resolve(out);
      } catch (e) { resolve({ ok: false, error: String((e && e.message) || e) }); }
    };
    recorder.stop();
  });
}