/**
 * Tractatus Service Worker
 * - Version management and update notifications
 * - Cache management for offline support
 * - PWA functionality
 */

const CACHE_VERSION = '1.0.8';
const CACHE_NAME = `tractatus-v${CACHE_VERSION}`;
const VERSION_CHECK_INTERVAL = 3600000; // 1 hour in milliseconds

// Assets to cache immediately on install
const CRITICAL_ASSETS = [
  '/',
  '/index.html',
  '/css/tailwind.css',
  '/js/components/navbar.js',
  '/images/tractatus-icon.svg',
  '/favicon.svg'
];

// Install event - cache critical assets
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('[Service Worker] Caching critical assets');
      return cache.addAll(CRITICAL_ASSETS);
    }).then(() => {
      // Force activation of new service worker
      return self.skipWaiting();
    })
  );
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames
          .filter((name) => name !== CACHE_NAME)
          .map((name) => {
            console.log('[Service Worker] Deleting old cache:', name);
            return caches.delete(name);
          })
      );
    }).then(() => {
      // Take control of all clients immediately
      return self.clients.claim();
    })
  );
});

// Fetch event - network-first strategy with cache fallback
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);

  // Skip chrome-extension and other non-http requests
  if (!url.protocol.startsWith('http')) {
    return;
  }

  // HTML files: Network-first (always check for updates)
  if (request.destination === 'document' || url.pathname.endsWith('.html')) {
    event.respondWith(
      fetch(request)
        .then((response) => {
          // Clone response to cache and return
          const responseClone = response.clone();
          caches.open(CACHE_NAME).then((cache) => {
            cache.put(request, responseClone);
          });
          return response;
        })
        .catch(() => {
          // If network fails, try cache
          return caches.match(request);
        })
    );
    return;
  }

  // Static assets (CSS, JS, images): Cache-first
  if (
    request.destination === 'style' ||
    request.destination === 'script' ||
    request.destination === 'image' ||
    request.destination === 'font'
  ) {
    event.respondWith(
      caches.match(request).then((cachedResponse) => {
        if (cachedResponse) {
          return cachedResponse;
        }
        return fetch(request).then((response) => {
          // Clone response to cache
          const responseClone = response.clone();
          caches.open(CACHE_NAME).then((cache) => {
            cache.put(request, responseClone);
          });
          return response;
        });
      })
    );
    return;
  }

  // API calls and other requests: Network-first
  event.respondWith(
    fetch(request)
      .then((response) => {
        return response;
      })
      .catch(() => {
        return caches.match(request);
      })
  );
});

// Message event - handle version checks from clients
self.addEventListener('message', (event) => {
  if (event.data.type === 'CHECK_VERSION') {
    checkVersion().then((versionInfo) => {
      event.ports[0].postMessage({
        type: 'VERSION_INFO',
        ...versionInfo
      });
    });
  }

  if (event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

// Check for version updates
async function checkVersion() {
  try {
    const response = await fetch('/version.json', { cache: 'no-store' });
    const serverVersion = await response.json();

    return {
      currentVersion: CACHE_VERSION,
      serverVersion: serverVersion.version,
      updateAvailable: CACHE_VERSION !== serverVersion.version,
      forceUpdate: serverVersion.forceUpdate,
      changelog: serverVersion.changelog
    };
  } catch (error) {
    console.error('[Service Worker] Version check failed:', error);
    return {
      currentVersion: CACHE_VERSION,
      serverVersion: null,
      updateAvailable: false,
      error: true
    };
  }
}

// Periodic background sync for version checks (if supported)
self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'version-check') {
    event.waitUntil(
      checkVersion().then((versionInfo) => {
        if (versionInfo.updateAvailable) {
          // Notify all clients about update
          self.clients.matchAll().then((clients) => {
            clients.forEach((client) => {
              client.postMessage({
                type: 'UPDATE_AVAILABLE',
                ...versionInfo
              });
            });
          });
        }
      })
    );
  }
});
