const SHELL_CACHE = 'tenant-admin-shell-v1';
const ASSET_CACHE = 'tenant-admin-assets-v1';

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(SHELL_CACHE).then((cache) => cache.addAll(['/event-admin']))
  );
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches
      .keys()
      .then((keys) =>
        Promise.all(
          keys
            .filter((key) => ![SHELL_CACHE, ASSET_CACHE].includes(key))
            .map((key) => caches.delete(key))
        )
      )
  );
  event.waitUntil(self.clients.claim());
});

self.addEventListener('fetch', (event) => {
  const { request } = event;
  if (request.method !== 'GET') return;

  const url = new URL(request.url);
  if (url.origin !== self.location.origin) return;

  // Allow API traffic to bypass the SW
  if (url.pathname.startsWith('/api/')) return;

  // Navigation requests for the admin shell
  if (request.mode === 'navigate' && url.pathname.startsWith('/event-admin')) {
    event.respondWith(
      (async () => {
        try {
          const networkResponse = await fetch(request);
          const cache = await caches.open(SHELL_CACHE);
          cache.put('/event-admin', networkResponse.clone());
          return networkResponse;
        } catch {
          const cached = await caches.match('/event-admin');
          if (cached) return cached;
          return Response.error();
        }
      })()
    );
    return;
  }

  // Static asset caching (CSS/JS/fonts)
  if (
    request.destination === 'style' ||
    request.destination === 'script' ||
    request.destination === 'font'
  ) {
    event.respondWith(
      (async () => {
        const cache = await caches.open(ASSET_CACHE);
        const cached = await cache.match(request);
        const fetchPromise = fetch(request)
          .then((response) => {
            if (response.ok) {
              cache.put(request, response.clone());
            }
            return response;
          })
          .catch(() => null);
        return cached || (await fetchPromise) || Response.error();
      })()
    );
    return;
  }

  // Images and icons (cache-first)
  if (
    request.destination === 'image' ||
    /\.(png|jpg|jpeg|webp|avif|gif|svg)(\?.*)?$/i.test(url.pathname)
  ) {
    event.respondWith(
      (async () => {
        const cache = await caches.open(ASSET_CACHE);
        const cached = await cache.match(request);
        if (cached) return cached;
        try {
          const response = await fetch(request);
          if (response.ok) cache.put(request, response.clone());
          return response;
        } catch {
          return cached || Response.error();
        }
      })()
    );
  }
});

self.addEventListener('push', (event) => {
  const payload = event.data?.json?.() ?? {};

  event.waitUntil(
    (async () => {
      const title = payload.title ?? 'Neue Admin-Benachrichtigung';
      const options = {
        body: payload.body ?? '',
        icon: '/admin-icon-192.png',
        badge: '/admin-badge.png',
        data: payload.data ?? {},
      };

      await self.registration.showNotification(title, options);

      const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
      clients.forEach((client) => client.postMessage({ type: 'admin-notification-refresh' }));
    })()
  );
});

self.addEventListener('notificationclick', (event) => {
  event.notification.close();
  const targetUrl = event.notification.data?.url || '/event-admin/mobile/notifications';

  event.waitUntil(
    self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
      for (const client of clientList) {
        if ('focus' in client) {
          client.navigate(targetUrl);
          return client.focus();
        }
      }
      if (self.clients.openWindow) {
        return self.clients.openWindow(targetUrl);
      }
    })
  );
});

self.addEventListener('pushsubscriptionchange', (event) => {
  event.waitUntil(
    self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
      clientList.forEach((client) => client.postMessage({ type: 'push-subscription-change' }));
    })
  );
});
