// psyc — minimal service worker.
// Strategy:
//   • static assets (CSS/JS/PNG)   → cache-first, fall back to network
//   • HTML pages and API responses → network-first (always fresh data)
// This makes the cockpit installable as a PWA and survives flaky connections,
// without serving stale operational data behind the operator's back.

const CACHE_VERSION = "psyc-v2";
const STATIC_ASSETS = [
  "/static/cockpit.css",
  "/static/psyc-tokens.css",
  "/static/psyc-logo.png",
  "/static/nn-sc-icon.png",
  "/static/manifest.json",
];

self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open(CACHE_VERSION).then((c) => c.addAll(STATIC_ASSETS)).catch(() => {})
  );
  self.skipWaiting();
});

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

function isStatic(req) {
  return /\.(css|js|png|svg|ico|woff2?)$/.test(new URL(req.url).pathname) ||
         new URL(req.url).pathname.startsWith("/static/");
}

self.addEventListener("fetch", (event) => {
  const req = event.request;
  if (req.method !== "GET") return;
  if (isStatic(req)) {
    // stale-while-revalidate: serve from cache for speed, refresh in the
    // background so subsequent loads pick up new CSS/JS without a manual
    // version bump. Falls back to network if the cache is cold.
    event.respondWith(
      caches.open(CACHE_VERSION).then((cache) =>
        cache.match(req).then((hit) => {
          const network = fetch(req).then((resp) => {
            if (resp && resp.ok) cache.put(req, resp.clone()).catch(() => {});
            return resp;
          }).catch(() => hit);
          return hit || network;
        })
      )
    );
  } else {
    // network-first for HTML + API
    event.respondWith(
      fetch(req).catch(() => caches.match(req).then((hit) => hit || new Response(
        "<!doctype html><meta charset=utf-8><title>psyc offline</title>" +
        "<style>body{background:#0f1115;color:#d8dee9;font-family:sans-serif;padding:40px;text-align:center}h1{color:#1ec8ff}</style>" +
        "<h1>psyc · offline</h1><p>The cockpit is offline. Reconnect to load fresh data.</p>",
        { headers: { "Content-Type": "text/html" } }
      )))
    );
  }
});
