// ==========================================
// Switchboard Core – Service Worker
// ==========================================
// Caches the app shell for offline / instant load.
// API calls always go to network (never cached).
//
// Cache key includes a build hash computed at container
// startup from the JS file contents. Every deploy produces
// a new hash, which triggers install → precache → activate
// → purge old caches automatically.

const CACHE_NAME = 'switchboard-%%APP_VERSION%%-%%BUILD_HASH%%';

// App shell files to pre-cache on install (cleaned up in v0.37.12)
const SHELL_FILES = [
    './',
    './index.html',
    // CSS — shared
    './css/variables.css',
    './css/layout.css',
    './css/primitives.css',
    './css/modals.css',
    './css/surfaces.css',
    './css/user-menu.css',
    './css/workflow.css',
    './css/admin-surfaces.css',
    './css/tool-grants.css',
    './css/extension-surface.css',
    // CSS — Preact (sw-*)
    './css/sw-primitives.css',
    './css/sw-shell.css',
    './css/sw-debug.css',
    './css/sw-login.css',
    './css/sw-chat-pane.css',
    './css/sw-chat-surface.css',
    './css/sw-notes-pane.css',
    './css/sw-notes-surface.css',
    // JS — debug tooling (v0.37.18: repl.js absorbed into Preact debug components)
    './js/debug.js',
    // Vendor
    './vendor/marked.min.js',
    './vendor/purify.min.js',
    // Static assets
    './favicon.svg',
    './favicon-light.svg',
    './favicon.ico',
    './favicon-32.png',
    './favicon-256.png',
    './manifest.json',
];

// Install: pre-cache the shell
self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => cache.addAll(SHELL_FILES))
            .then(() => self.skipWaiting())
    );
});

// Activate: purge old caches
self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys().then(keys =>
            Promise.all(
                keys.filter(k => k !== CACHE_NAME)
                    .map(k => caches.delete(k))
            )
        ).then(() => self.clients.claim())
    );
});

// Fetch: network-first for API/WS, stale-while-revalidate for shell assets
self.addEventListener('fetch', (event) => {
    const url = new URL(event.request.url);

    // Only handle http/https — ignore chrome-extension://, moz-extension://, etc.
    if (url.protocol !== 'https:' && url.protocol !== 'http:') {
        return;
    }

    // Never cache API calls, WebSocket upgrades, branding, extensions, or CM6 bundle
    if (url.pathname.includes('/api/') ||
        url.pathname.includes('/ws') ||
        url.pathname.includes('/branding/') ||
        url.pathname.includes('/extensions/') ||
        url.pathname.includes('/vendor/codemirror/') ||
        event.request.method !== 'GET') {
        return;
    }

    // Stale-while-revalidate: serve cached, update in background
    event.respondWith(
        caches.match(event.request).then(cached => {
            const fetchPromise = fetch(event.request).then(response => {
                // Update cache with fresh version
                if (response.ok) {
                    const clone = response.clone();
                    caches.open(CACHE_NAME).then(cache => cache.put(event.request, clone));
                }
                return response;
            }).catch(() => cached); // offline fallback to cache

            return cached || fetchPromise;
        })
    );
});
