/// <reference types="@sveltejs/kit" />
/// <reference lib="webworker" />

import type { ApiEnvelope } from '@owlboard/api-schema-types';
import { build, files, version } from '$service-worker';

const sw = self as unknown as ServiceWorkerGlobalScope;
const CACHE_NAME = `owlboard-cache-${version}`;
const ASSETS = [...build, ...files, '/'];

sw.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS))
    );
});

sw.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys().then((keys) => {
            return Promise.all(
                keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))
            );
        })
    );
});

sw.addEventListener('fetch', (event) => {
    const { request } = event;
    if (request.method !== 'GET') return;
    
    const url = new URL(request.url);

    // 1. Static Assets (Cache-First)
    if (ASSETS.includes(url.pathname) || url.pathname.startsWith('/_app/')) {
        event.respondWith(
            caches.match(request).then((res) => res || fetch(request))
        );
        return;
    }

    // 2. Offline API Fallback (Network-First)
    if (url.pathname.startsWith('/api') || url.hostname.includes('api')) {
        event.respondWith(
            fetch(request).catch(() => {
                const errorObject: ApiEnvelope.Envelope = {
                    e: {
                        code: "NETWORK_DISCONNECTED",
                        msg: "Cannot connect to the OwlBoard server"
                    },
                    t: Math.floor(Date.now() / 1000)
                };
                return new Response(
                    JSON.stringify(errorObject),
                    {
                        status: 503,
                        headers: { 'Content-Type': 'application/json' }
                    }
                );
            })
        );
        return;
    }

    // 3. Navigation Fallback (The Offline 404 Catch-All)
    // This catches top-level page navigations and hard refreshes
    if (request.mode === 'navigate' || request.headers.get('accept')?.includes('text/html')) {
        event.respondWith(
            fetch(request).catch(() => {
                // The network request failed entirely (offline).
                // Serve the cached root shell so SvelteKit can boot.
                return caches.match('/') as Promise<Response>;
            })
        );
        return;
    }
});