const CACHE_NAME = "espj-upst-pwa-v2";
const OFFLINE_URL = "/driver/offline.html";
const PRECACHE_URLS = [
    "/upst",
    "/upst/kosong",
    "/driver/manifest.json",
    "/driver/favicon.ico",
    "/driver/images/pwa_192.png",
    "/driver/images/pwa_512.png",
    OFFLINE_URL
];

self.addEventListener("install", (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME).then(async (cache) => {
            const results = await Promise.allSettled(
                PRECACHE_URLS.map(async (url) => {
                    const response = await fetch(url, { cache: "no-store" });
                    if (!response.ok) {
                        throw new Error(`Gagal precache: ${url} (${response.status})`);
                    }

                    await cache.put(url, response.clone());
                })
            );

            const offlineCached = results.some(
                (result, index) =>
                    PRECACHE_URLS[index] === OFFLINE_URL && result.status === "fulfilled"
            );

            if (!offlineCached) {
                throw new Error(`Offline page gagal diprecache: ${OFFLINE_URL}`);
            }
        })
    );
    self.skipWaiting();
});

self.addEventListener("activate", (event) => {
    event.waitUntil(
        caches.keys().then((keys) =>
            Promise.all(
                keys
                    .filter((key) => key !== CACHE_NAME)
                    .map((key) => caches.delete(key))
            )
        )
    );

    self.clients.claim();
});

const AUTH_PATHS = [
    "/signin-oidc",
    "/signout-callback-oidc",
    "/signout-oidc",
    "/connect/",
    "/Identity/",
    "/.well-known/",
];

function isAuthPath(url) {
    return AUTH_PATHS.some((path) => url.pathname.startsWith(path));
}

const BYPASS_CACHE_PATHS = [
    "/upst/detail-penjemputan/api/",
    "/uploads/penjemputan/",
    "/driver/json/"
];

function shouldBypassCache(url) {
    return BYPASS_CACHE_PATHS.some((path) => url.pathname.startsWith(path));
}

self.addEventListener("fetch", (event) => {
    const { request } = event;
    const url = new URL(request.url);

    if (request.method !== "GET") {
        return;
    }

    if (url.origin !== self.location.origin) {
        return;
    }

    if (isAuthPath(url)) {
        return;
    }

    if (shouldBypassCache(url)) {
        event.respondWith(
            fetch(new Request(request, { cache: "no-store" })).catch(async () => {
                if (request.mode === "navigate") {
                    return (await caches.match(OFFLINE_URL)) || Response.error();
                }

                return Response.error();
            })
        );
        return;
    }

    if (request.mode === "navigate") {
        event.respondWith(
            fetch(request)
                .then((response) => {
                    if (url.pathname.startsWith("/upst")) {
                        const responseClone = response.clone();
                        caches.open(CACHE_NAME).then((cache) => cache.put(request, responseClone));
                    }
                    return response;
                })
                .catch(async () => {
                    const cachedPage = await caches.match(request);
                    return cachedPage || (await caches.match(OFFLINE_URL)) || Response.error();
                })
        );
        return;
    }

    if (url.origin !== self.location.origin) {
        return;
    }

    event.respondWith(
        caches.match(request).then((cachedResponse) => {
            const networkFetch = fetch(request)
                .then((response) => {
                    if (response && response.ok) {
                        const responseClone = response.clone();
                        caches.open(CACHE_NAME).then((cache) => cache.put(request, responseClone));
                    }
                    return response;
                })
                .catch(() => cachedResponse);

            return cachedResponse || networkFetch;
        })
    );
});
