// Paliad service worker. Cache strategy:
//   /assets/* + /icons/*  → cache-first  (immutable per deploy)
//   /api/*                → network-first (fall back to cached snapshot)
//   everything else       → network passthrough
//
// CACHE_VERSION is rewritten to "v<build-epoch-ms>" by frontend/build.ts on
// every deploy. The activate handler deletes ANY cache whose name doesn't
// match — covers both prior versioned caches (v17143…) and any pre-versioning
// cache name (paliad-v1-static, t-paliad-043 kill-switch survivors). This is
// what guarantees a stale `/assets/projects.js` from a previous deploy gets
// purged the moment the new SW activates, instead of lingering until the user
// manually clears site data.

const CACHE_VERSION = "__PALIAD_BUILD_VERSION__";
const STATIC_CACHE = `${CACHE_VERSION}-static`;

self.addEventListener("install", () => {
  // skipWaiting so the new SW takes over the moment install completes,
  // rather than waiting for every tab to close. Combined with clients.claim
  // in activate, this means a deploy reaches users on their next navigation.
  self.skipWaiting();
});

self.addEventListener("activate", (event) => {
  event.waitUntil(
    (async () => {
      const keys = await caches.keys();
      await Promise.all(
        keys.filter((k) => k !== STATIC_CACHE).map((k) => caches.delete(k)),
      );
      await self.clients.claim();
    })(),
  );
});

self.addEventListener("fetch", (event) => {
  const req = event.request;
  if (req.method !== "GET") return;

  const url = new URL(req.url);
  if (url.origin !== self.location.origin) return;

  if (url.pathname.startsWith("/assets/") || url.pathname.startsWith("/icons/")) {
    event.respondWith(cacheFirst(req));
    return;
  }

  if (url.pathname.startsWith("/api/")) {
    event.respondWith(networkFirst(req));
    return;
  }
});

async function cacheFirst(req) {
  const cache = await caches.open(STATIC_CACHE);
  const cached = await cache.match(req);
  if (cached) return cached;
  try {
    // cache: "reload" forces the network leg to BYPASS the browser HTTP
    // cache. Without this, a stale /assets/projects.js sitting in the
    // browser's disk cache from a previous deploy would be returned to us,
    // we'd cache it again, and the user would be stuck on the old bundle
    // forever — exactly the failure mode that caused t-paliad-043.
    const res = await fetch(req, { cache: "reload" });
    if (res && res.ok) cache.put(req, res.clone());
    return res;
  } catch (err) {
    if (cached) return cached;
    throw err;
  }
}

async function networkFirst(req) {
  try {
    return await fetch(req);
  } catch (err) {
    const cache = await caches.open(STATIC_CACHE);
    const cached = await cache.match(req);
    if (cached) return cached;
    throw err;
  }
}
