// src/sw.ts
// Make sure this file is in src/ as configured in vite.config.ts (srcDir & filename)

// Ensure globalThis.skipWaiting and clientsClaim are available in the SW scope
/// <reference lib="webworker" />

declare const self: ServiceWorkerGlobalScope &
  typeof globalThis & {
    skipWaiting: () => Promise<void>;
    __WB_MANIFEST: Array<{ url: string; revision: string | null }>;
  };

import { clientsClaim } from 'workbox-core';
import {
  precacheAndRoute,
  cleanupOutdatedCaches,
  createHandlerBoundToURL,
} from 'workbox-precaching';
import { registerRoute, NavigationRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { BackgroundSyncPlugin } from 'workbox-background-sync';
import type { WorkboxPlugin } from 'workbox-core/types';

// Create a background sync plugin instance
const bgSyncPlugin = new BackgroundSyncPlugin('offline-actions-queue', {
  maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});

// Initialize service worker
const initializeSW = async () => {
  try {
    await self.skipWaiting();
    clientsClaim();
    // console.log('Service Worker initialized successfully');
  } catch (error) {
    console.error('Error during service worker initialization:', error);
  }
};

// Use with precache injection
// vite-plugin-pwa will populate self.__WB_MANIFEST
precacheAndRoute(self.__WB_MANIFEST);

cleanupOutdatedCaches();

// Cache app shell and static assets with Cache First strategy
registerRoute(
  ({ request }) =>
    request.destination === 'style' ||
    request.destination === 'script' ||
    request.destination === 'image' ||
    request.destination === 'font',
  new CacheFirst({
    cacheName: 'static-assets',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }) as WorkboxPlugin,
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
      }) as WorkboxPlugin,
    ],
  })
);

// Cache API calls with Network First strategy and Background Sync for failed requests
registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'), // Make sure this matches your actual API path structure
  new NetworkFirst({
    cacheName: 'api-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }) as WorkboxPlugin,
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 24 * 60 * 60, // 24 hours
      }) as WorkboxPlugin,
      bgSyncPlugin, // Add background sync plugin for failed requests
    ],
  })
);

// Non-SSR fallbacks to index.html
// Production SSR fallbacks to offline.html (except for dev)
// Using environment variables defined in vite.config.ts and injected by Vite
declare const __PWA_FALLBACK_HTML__: string;
declare const __PWA_SERVICE_WORKER_REGEX__: string;

// Use fallback values if not defined
const PWA_FALLBACK_HTML = typeof __PWA_FALLBACK_HTML__ !== 'undefined' ? __PWA_FALLBACK_HTML__ : '/index.html';
const PWA_SERVICE_WORKER_REGEX = typeof __PWA_SERVICE_WORKER_REGEX__ !== 'undefined'
  ? new RegExp(__PWA_SERVICE_WORKER_REGEX__)
  : /^(sw|workbox)-.*\.js$/;

// Register navigation route for SPA fallback
if (import.meta.env.MODE !== 'ssr' || import.meta.env.PROD) {
  // Cache the index.html explicitly for navigation fallback
  registerRoute(
    ({ request }) => request.mode === 'navigate',
    new NetworkFirst({
      cacheName: 'navigation-cache',
      plugins: [
        new CacheableResponsePlugin({
          statuses: [0, 200],
        }) as WorkboxPlugin,
      ],
    })
  );

  // Register fallback for offline navigation
  registerRoute(
    new NavigationRoute(createHandlerBoundToURL(PWA_FALLBACK_HTML), {
      denylist: [PWA_SERVICE_WORKER_REGEX, /workbox-(.)*\.js$/],
    }),
  );
}

// Initialize the service worker
initializeSW();