const CACHE_NAME = "roast-planner-static-__ASSET_VERSION__";
// Only /app is precached as a navigable page: it is a data-free authenticated shell (draft
// data lives only in account-scoped local storage, and logout clears that namespace), so it is
// the one page that is both safe and useful to relaunch offline. The marketing page, auth
// pages, account, admin, inventory, and cupping all depend on the network (auth checks, live
// data) and are deliberately left off this list rather than cached in a way that could show
// stale content.
const APP_SHELL = [
	"/app",
	"/app.css?v=__ASSET_VERSION__",
	"/worksheet.css?v=__ASSET_VERSION__",
	"/manifest.webmanifest?v=__ASSET_VERSION__",
	"/icon.svg?v=__ASSET_VERSION__",
	"/js/main.js?v=__ASSET_VERSION__",
	"/js/api.js?v=__ASSET_VERSION__",
	"/js/nav.js?v=__ASSET_VERSION__",
	"/js/toast.js?v=__ASSET_VERSION__",
	"/js/why-panels.js?v=__ASSET_VERSION__",
	"/js/field-help.js?v=__ASSET_VERSION__",
	"/js/field-help-content.js?v=__ASSET_VERSION__",
	"/js/lot-picker.js?v=__ASSET_VERSION__",
	"/js/plan-chat-ui.js?v=__ASSET_VERSION__",
	"/js/prefill-ui.js?v=__ASSET_VERSION__",
	"/js/alog-ui.js?v=__ASSET_VERSION__",
	"/js/print.js?v=__ASSET_VERSION__",
	"/shared/fields.js?v=__ASSET_VERSION__",
	"/shared/ledger.js?v=__ASSET_VERSION__",
	"/shared/time.js?v=__ASSET_VERSION__",
	"/shared/reference-data.js?v=__ASSET_VERSION__",
	"/shared/curve.js?v=__ASSET_VERSION__",
	"/shared/cupping.js?v=__ASSET_VERSION__",
];

self.addEventListener("install", (event) => {
	event.waitUntil(
		caches.open(CACHE_NAME).then((cache) => cache.addAll(APP_SHELL)),
	);
});

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();
});

self.addEventListener("fetch", (event) => {
	const { request } = event;
	let url;
	try {
		url = new URL(request.url);
	} catch {
		return;
	}
	if (
		request.method !== "GET" ||
		url.origin !== self.location.origin ||
		url.pathname.startsWith("/api/")
	)
		return;

	if (request.mode === "navigate") {
		// Only /app has a meaningful offline shell (see APP_SHELL comment above); every other
		// page requires the network anyway, so let those navigations fail normally when offline
		// rather than risk serving stale auth/account/admin content.
		if (url.pathname !== "/app") return;
		event.respondWith(
			fetch(request).catch(
				async () => (await caches.match("/app")) || Response.error(),
			),
		);
		return;
	}

	// Prefer fresh JavaScript and styles so installed clients receive UI/security updates
	// immediately; use the cache only when offline.
	event.respondWith(
		fetch(request)
			.then((response) => {
				if (response.ok)
					caches
						.open(CACHE_NAME)
						.then((cache) => cache.put(request, response.clone()));
				return response;
			})
			.catch(() => caches.match(request)),
	);
});

self.addEventListener("message", (event) => {
	if (event.data === "SKIP_WAITING") self.skipWaiting();
});
