// Web Push subscription registration. Browser-only; Tauri WebView2 / WebKit
// do not install service workers. The Tauri build relies on native OS
// notifications via osNotify.ts instead.
//
// Flow:
//   1. Register /sw.js if not already.
//   2. Subscribe with the VAPID public key (Vite injects it via env).
//   3. Persist {endpoint, keys} JSON-encoded into push_tokens.token for the
//      current device. Server-side fan-out reads this row to send pushes.

import { isTauriRuntime } from './globalShortcut';
import { supabase } from './supabase';

const VAPID_PUBLIC_KEY: string | undefined =
  (import.meta as unknown as { env?: { VITE_VAPID_PUBLIC_KEY?: string } }).env
    ?.VITE_VAPID_PUBLIC_KEY;

export async function registerWebPush(deviceId: string): Promise<void> {
  // Tauri uses native notifications — no service worker.
  if (isTauriRuntime()) return;
  if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) return;
  if (!('PushManager' in window)) return;
  if (!VAPID_PUBLIC_KEY) {
    console.warn('VITE_VAPID_PUBLIC_KEY not set — push disabled');
    return;
  }

  try {
    const reg = await navigator.serviceWorker.register('/sw.js');
    await navigator.serviceWorker.ready;
    let sub = await reg.pushManager.getSubscription();
    if (!sub) {
      const permission = await Notification.requestPermission();
      if (permission !== 'granted') return;
      sub = await reg.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY) as BufferSource,
      });
    }

    const token = JSON.stringify({
      endpoint: sub.endpoint,
      keys: sub.toJSON().keys ?? {},
    });

    const { error } = await supabase
      .from('push_tokens')
      .upsert(
        { device_id: deviceId, platform: 'web' as never, token },
        { onConflict: 'device_id' },
      );
    if (error) {
      console.warn('push_tokens upsert failed', error);
    }
  } catch (err: unknown) {
    console.error('registerWebPush failed', err);
  }
}

export async function unregisterWebPush(deviceId: string): Promise<void> {
  if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) return;
  try {
    const reg = await navigator.serviceWorker.getRegistration();
    if (reg) {
      const sub = await reg.pushManager.getSubscription();
      if (sub) await sub.unsubscribe();
    }
  } catch {
    /* ignore */
  }
  try {
    await supabase.from('push_tokens').delete().eq('device_id', deviceId);
  } catch (err: unknown) {
    console.warn('push_tokens delete failed', err);
  }
}

// VAPID public key arrives as URL-safe base64; PushManager expects a raw byte
// array. Standard conversion.
function urlBase64ToUint8Array(base64: string): Uint8Array {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4);
  const padded = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/');
  const raw = atob(padded);
  const out = new Uint8Array(raw.length);
  for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
  return out;
}
