// src/generateServiceWorkerFile.ts

/**
 * Generates a complete Service Worker file string based on provided caching strategy routes.
 * @param config - Object containing arrays of routes for each strategy.
 * @returns A string representing the content of the sw.js file.
 */
export function generateServiceWorkerFile(config: {
  cacheFirstRoutes: string[];
  networkFirstRoutes: string[];
  staleWhileRevalidateRoutes: string[];
}): string {
  const { cacheFirstRoutes, networkFirstRoutes, staleWhileRevalidateRoutes } =
    config;

  // Helper to stringify route conditions
  const formatRouteConditions = (
    routes: string[],
    strategyFn: string
  ): string => {
    return routes
      .map(
        (route) =>
          `  if (url.pathname.startsWith('${route}')) return ${strategyFn}(event);`
      )
      .join("\n");
  };

  return `
// ---- Service Worker (Auto-Generated) ----

/**
 * Service Worker Install Event - activates immediately.
 */
self.addEventListener('install', (event) => {
  self.skipWaiting();
});

/**
 * Service Worker Activate Event - takes control of uncontrolled clients.
 */
self.addEventListener('activate', (event) => {
  self.clients.claim();
});

/**
 * Fetch Event Handler
 * Applies caching strategies based on route pattern matching.
 */
self.addEventListener('fetch', (event) => {
  const url = new URL(event.request.url);

${formatRouteConditions(cacheFirstRoutes, "cacheFirst")}
${formatRouteConditions(networkFirstRoutes, "networkFirst")}
${formatRouteConditions(staleWhileRevalidateRoutes, "staleWhileRevalidate")}
});

/**
 * ---- Caching Strategy Implementations ----
 */

/**
 * Cache First Strategy
 * Serves from cache if available, otherwise fetches from network and caches it.
 */
async function cacheFirst(event) {
  const cache = await caches.open('app-cache');
  const cachedResponse = await cache.match(event.request);
  if (cachedResponse) return cachedResponse;

  const networkResponse = await fetch(event.request);
  cache.put(event.request, networkResponse.clone());
  return networkResponse;
}

/**
 * Network First Strategy
 * Tries to fetch from network first; if fails, returns cached version if available.
 */
async function networkFirst(event) {
  const cache = await caches.open('app-cache');
  try {
    const networkResponse = await fetch(event.request);
    cache.put(event.request, networkResponse.clone());
    return networkResponse;
  } catch (error) {
    const cachedResponse = await cache.match(event.request);
    return cachedResponse || new Response('Network error and no cache.', { status: 503 });
  }
}

/**
 * Stale While Revalidate Strategy
 * Returns cached version immediately while revalidating cache in the background.
 */
async function staleWhileRevalidate(event) {
  const cache = await caches.open('app-cache');
  const cachedResponse = await cache.match(event.request);

  const fetchPromise = fetch(event.request)
    .then((networkResponse) => {
      cache.put(event.request, networkResponse.clone());
      return networkResponse;
    })
    .catch(() => {});

  return cachedResponse || fetchPromise;
}
`;
}
