// RangerHQ Tuner — Service Worker.
// Job: open the offscreen audio document on demand and route messages
// between the popup/newtab (UI) and the offscreen document (audio engine).
// Also acts as the storage gateway for the offscreen doc — offscreen
// docs don't reliably have chrome.storage, so they message us instead.
// We hold no in-memory state here — Chrome will kill this worker at any time.

import { TARGETS, TYPES } from '../lib/messages.js';
import { logTrack } from '../lib/history.js';

const OFFSCREEN_PATH = 'src/offscreen/offscreen.html';

async function ensureOffscreen() {
  // hasDocument is the official MV3 way to check. Optional-chained
  // for older Chrome safety (we still require 116+ via the manifest).
  const exists = await chrome.offscreen.hasDocument?.();
  if (exists) return;
  await chrome.offscreen.createDocument({
    url: OFFSCREEN_PATH,
    reasons: ['AUDIO_PLAYBACK'],
    justification: 'Persistent audio playback for internet radio streams.',
  });
}

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  // Only react to messages targeted at the service worker.
  if (msg.target !== TARGETS.SW) return;

  (async () => {
    try {
      // Storage-gateway path: write to chrome.storage on behalf of the
      // offscreen document, which can't always reach it directly.
      if (msg.type === TYPES.LOG_TRACK_REQUEST) {
        const appended = await logTrack(msg.entry || {});
        if (appended) {
          chrome.runtime.sendMessage({
            target: TARGETS.POPUP,
            type:   TYPES.TRACK_LOGGED,
          }).catch(() => {}); // no UI listening is fine
        }
        sendResponse({ ok: true, appended });
        return;
      }

      // Default: forward audio-control messages to the offscreen doc.
      await ensureOffscreen();
      const response = await chrome.runtime.sendMessage({
        ...msg,
        target: TARGETS.OFFSCREEN,
      });
      sendResponse(response);
    } catch (err) {
      sendResponse({ ok: false, error: err.message });
    }
  })();

  return true; // keep the channel open for async sendResponse
});
