const VG_SW_VERSION = 'auth-cold-start-v9';
const VG_SW_ACTIVATION_MARKER = `videograce-sw-${VG_SW_VERSION}`;

self.addEventListener('install', () => self.skipWaiting());

self.addEventListener('message', (event) => {
  if (event.data?.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    const existingCaches = await caches.keys();
    const firstActivation = !existingCaches.includes(VG_SW_ACTIVATION_MARKER);
    await caches.open(VG_SW_ACTIVATION_MARKER);
    await self.clients.claim();

    // Installed PWAs can restore a frozen window that keeps executing an old
    // entry bundle. Force one real navigation when this recovery worker first
    // takes control; subsequent starts are unaffected.
    if (firstActivation) {
      const clientList = await self.clients.matchAll({
        type: 'window',
        includeUncontrolled: true,
      });
      await Promise.all(clientList.map((client) => {
        if (!('navigate' in client)) return Promise.resolve();
        return client.navigate(client.url).catch(() => null);
      }));
    }
  })());
});

function parseJsonObject(text) {
  if (!text || typeof text !== 'string') {
    return null;
  }

  try {
    const parsed = JSON.parse(text);
    return parsed && typeof parsed === 'object' ? parsed : null;
  } catch {
    return null;
  }
}

function normalizePushPayload(rawPayload) {
  const cleanRawPayload = String(rawPayload || '').replace(/[\u0000-\u001f]+$/g, '').trim();
  let payload = { title: 'VideoGrace', body: cleanRawPayload, url: '/' };
  const parsed = parseJsonObject(cleanRawPayload);

  if (parsed) {
    payload = {
      ...payload,
      ...parsed,
    };
  }

  if (payload.notification && typeof payload.notification === 'object') {
    payload = {
      ...payload,
      ...payload.notification,
    };
  }

  if (payload.data && typeof payload.data === 'object') {
    payload = {
      ...payload,
      ...payload.data,
    };
  }

  for (let i = 0; i < 2; i += 1) {
    if (typeof payload.body !== 'string') {
      payload.body = '';
      break;
    }

    const nested = parseJsonObject(payload.body.trim());
    if (!nested) {
      break;
    }

    payload = {
      ...payload,
      ...nested,
    };
  }

  if (typeof payload.message === 'string' && payload.message.trim()) {
    payload.body = payload.message;
  } else if (typeof payload.preview === 'string' && payload.preview.trim()) {
    payload.body = payload.preview;
  } else if (typeof payload.text === 'string' && payload.text.trim()) {
    payload.body = payload.text;
  }

  if (payload.type === 'message') {
    const author = typeof payload.author === 'string' ? payload.author.trim() : '';
    const authorName = typeof payload.author_name === 'string' ? payload.author_name.trim() : '';
    const senderName = typeof payload.sender_name === 'string' ? payload.sender_name.trim() : '';
    const conference = typeof payload.conference === 'string' ? payload.conference.trim() : '';
    const conferenceName = typeof payload.conference_name === 'string' ? payload.conference_name.trim() : '';
    const name = author || authorName || senderName;
    const room = conference || conferenceName;
    if (name && room) {
      payload.title = `${name} @ ${room}`;
    } else if (name) {
      payload.title = name;
    } else if (room) {
      payload.title = room;
    } else if (!payload.title || payload.title === 'VideoGrace') {
      payload.title = 'Новое сообщение';
    }
  }

  if (typeof payload.title !== 'string' || !payload.title.trim()) {
    payload.title = 'VideoGrace';
  }

  if (typeof payload.body !== 'string') {
    payload.body = '';
  }

  if (payload.body.trim().startsWith('{')) {
    payload.body = 'Новое событие';
  }

  return payload;
}

function resolveNotificationUrl(value) {
  const scopeUrl = new URL(self.registration.scope);

  try {
    const targetUrl = new URL(value || '/', scopeUrl.href);
    if (targetUrl.origin !== scopeUrl.origin || !targetUrl.href.startsWith(scopeUrl.href)) {
      return scopeUrl.href;
    }
    return targetUrl.href;
  } catch {
    return scopeUrl.href;
  }
}

self.addEventListener('push', (event) => {
  const rawPayload = event.data?.text?.() || '';
  const payload = normalizePushPayload(rawPayload);
  const targetUrl = resolveNotificationUrl(payload.url || payload.link || payload.click_action || '/');

  event.waitUntil(
    self.registration.showNotification(payload.title || 'VideoGrace', {
      body: payload.body || '',
      icon: '/icons/icon-192.png',
      badge: '/icons/favicon-32.png',
      data: { ...payload, url: targetUrl, swVersion: VG_SW_VERSION },
    })
  );
});

async function focusClient(client, targetUrl) {
  if (!client) {
    return null;
  }

  let focusedClient = client;
  if ('navigate' in focusedClient && !focusedClient.url.startsWith(targetUrl)) {
    focusedClient = await focusedClient.navigate(targetUrl).catch(() => null) || focusedClient;
  }

  if ('focus' in focusedClient) {
    return await focusedClient.focus().catch(() => null);
  }

  return null;
}

self.addEventListener('notificationclick', (event) => {
  event.notification.close();

  const notificationData = event.notification.data || {};
  const targetUrl = resolveNotificationUrl(
    notificationData.url || notificationData.link || notificationData.click_action || '/'
  );
  const scopeUrl = self.registration.scope;

  event.waitUntil((async () => {
    const clientList = await clients.matchAll({
      type: 'window',
      includeUncontrolled: true,
    });

    const client =
      clientList.find((entry) => entry.url.startsWith(targetUrl)) ||
      clientList.find((entry) => entry.url.startsWith(scopeUrl)) ||
      clientList[0];

    const focused = await focusClient(client, targetUrl);
    if (focused) {
      focused.postMessage({
        type: 'notification_click',
        data: notificationData,
      });
      return;
    }

    try {
      const opened = await clients.openWindow(targetUrl);
      opened?.postMessage?.({
        type: 'notification_click',
        data: notificationData,
      });
      if (!opened && targetUrl !== scopeUrl) {
        await clients.openWindow(scopeUrl);
      }
    } catch {
      if (targetUrl !== scopeUrl) {
        await clients.openWindow(scopeUrl);
      }
    }
  })());
});
