// rMaps Service Worker for Push Notifications & Background Location
const CACHE_NAME = 'rmaps-v1';
const SYNC_TAG = 'rmaps-location-sync';

// Install event - cache essential assets
self.addEventListener('install', (event) => {
  console.log('[SW] Installing service worker...');
  self.skipWaiting();
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
  console.log('[SW] Activating service worker...');
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames
          .filter((name) => name !== CACHE_NAME)
          .map((name) => caches.delete(name))
      );
    })
  );
  self.clients.claim();
});

// Background Sync - triggered when device comes back online
self.addEventListener('sync', (event) => {
  console.log('[SW] Sync event:', event.tag);

  if (event.tag === SYNC_TAG) {
    event.waitUntil(syncLocation());
  }
});

// Sync location to server when coming back online
async function syncLocation() {
  try {
    // Get stored location data from IndexedDB or localStorage via client
    const clients = await self.clients.matchAll({ type: 'window' });

    for (const client of clients) {
      // Ask the client to send its current location
      client.postMessage({ type: 'REQUEST_LOCATION_SYNC' });
    }

    console.log('[SW] Location sync requested from clients');
  } catch (error) {
    console.error('[SW] Location sync failed:', error);
  }
}

// Request location from any available client
async function requestLocationFromClient() {
  const clients = await self.clients.matchAll({
    type: 'window',
    includeUncontrolled: true
  });

  if (clients.length > 0) {
    // Send message to first available client to get location
    clients[0].postMessage({ type: 'REQUEST_LOCATION_UPDATE' });
    return true;
  }
  return false;
}

// Push event - handle incoming push notifications
self.addEventListener('push', (event) => {
  console.log('[SW] Push received:', event);

  let data = {
    title: 'rMaps',
    body: 'You have a new notification',
    icon: '/icon-192.png',
    badge: '/icon-192.png',
    tag: 'rmaps-notification',
    data: {},
    silent: false,
  };

  if (event.data) {
    try {
      const payload = event.data.json();
      data = { ...data, ...payload };
    } catch (e) {
      data.body = event.data.text();
    }
  }

  // Handle silent push - request location update without showing notification
  if (data.silent || data.data?.type === 'location_request') {
    event.waitUntil(
      requestLocationFromClient().then((sent) => {
        console.log('[SW] Silent push - location request sent:', sent);
      })
    );
    return;
  }

  const options = {
    body: data.body,
    icon: data.icon || '/icon-192.png',
    badge: data.badge || '/icon-192.png',
    tag: data.tag || 'rmaps-notification',
    data: data.data || {},
    // Strong vibration pattern: buzz-pause-buzz-pause-long buzz
    vibrate: [200, 100, 200, 100, 400],
    actions: data.actions || [],
    requireInteraction: data.requireInteraction || false,
    // Use default system notification sound
    silent: false,
    // Renotify even if same tag (so user hears it again)
    renotify: true,
  };

  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

// Notification click event - handle user interaction
self.addEventListener('notificationclick', (event) => {
  console.log('[SW] Notification clicked:', event);

  event.notification.close();

  const data = event.notification.data || {};
  let targetUrl = '/';

  // Determine URL based on notification type
  if (data.roomSlug) {
    targetUrl = `/${data.roomSlug}`;
  } else if (data.url) {
    targetUrl = data.url;
  }

  // Handle action buttons
  if (event.action === 'view') {
    targetUrl = data.url || targetUrl;
  } else if (event.action === 'dismiss') {
    return;
  }

  event.waitUntil(
    clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
      // Try to focus an existing window
      for (const client of clientList) {
        if (client.url.includes(targetUrl) && 'focus' in client) {
          return client.focus();
        }
      }
      // Open a new window if none exists
      if (clients.openWindow) {
        return clients.openWindow(targetUrl);
      }
    })
  );
});

// Handle notification close
self.addEventListener('notificationclose', (event) => {
  console.log('[SW] Notification closed:', event);
});

// Handle messages from the main thread
self.addEventListener('message', (event) => {
  console.log('[SW] Message received:', event.data);

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