// SparkSoftware Reporting — service worker (PWA).
// Static shell: stale-while-revalidate. Data (/api, /reports): network only,
// with a friendly JSON error when offline. Navigations fall back to the
// cached shell so the app still opens with no connection.
const VERSION = 'lp-v1';
const SHELL = [
  '/', '/app.js', '/theme.css', '/manifest.webmanifest',
  '/icon-192.png', '/icon-512.png', '/icon-maskable-512.png', '/apple-touch-icon.png',
];

self.addEventListener('install', (e) => {
  e.waitUntil(caches.open(VERSION).then((c) => c.addAll(SHELL)).then(() => self.skipWaiting()));
});

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

self.addEventListener('fetch', (e) => {
  const req = e.request;
  if (req.method !== 'GET') return; // POSTs (chat, reports, auth) go straight through
  const url = new URL(req.url);
  if (url.origin !== location.origin) return;

  // Live data — never serve stale numbers from cache.
  if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/reports/')) {
    e.respondWith(
      fetch(req).catch(() =>
        new Response(JSON.stringify({ error: 'You are offline — reconnect to load live data.' }),
          { status: 503, headers: { 'Content-Type': 'application/json' } }))
    );
    return;
  }

  // App shell (/, app.js, theme.css) — NETWORK FIRST so dashboard updates
  // apply on the very next load; the cache is the offline fallback only.
  const isCore = url.pathname === '/' || url.pathname === '/app.js' || url.pathname === '/theme.css' || req.mode === 'navigate';
  if (isCore) {
    e.respondWith(
      fetch(req)
        .then((res) => {
          if (res && res.ok) {
            const copy = res.clone();
            caches.open(VERSION).then((c) => c.put(req, copy));
          }
          return res;
        })
        .catch(() => caches.match(req, { ignoreSearch: true }).then((hit) => hit || caches.match('/')))
    );
    return;
  }

  // Icons / manifest — cached copy immediately, refreshed in the background.
  e.respondWith(
    caches.match(req).then((hit) => {
      const refresh = fetch(req)
        .then((res) => {
          if (res && res.ok) {
            const copy = res.clone();
            caches.open(VERSION).then((c) => c.put(req, copy));
          }
          return res;
        })
        .catch(() => null);
      return hit || refresh.then((res) => res || Response.error());
    })
  );
});
