// Client-side Web Push: feature detection + subscribe/unsubscribe round trip.
// Everything degrades silently — no key from the server, no UI.

function b64ToUint8(base64: string): Uint8Array {
  const pad = '='.repeat((4 - (base64.length % 4)) % 4);
  const raw = atob((base64 + pad).replace(/-/g, '+').replace(/_/g, '/'));
  return Uint8Array.from(raw, (c) => c.charCodeAt(0));
}

export const pushSupported = (): boolean =>
  'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;

let keyCache: Promise<string | null> | null = null;
export function serverPushKey(): Promise<string | null> {
  keyCache ??= fetch('/api/push/key')
    .then((r) => (r.ok ? r.json() : null))
    .then((d: { key: string } | null) => d?.key ?? null)
    .catch(() => null);
  return keyCache;
}

export async function currentSubscription(): Promise<PushSubscription | null> {
  if (!pushSupported()) return null;
  const reg = await navigator.serviceWorker.ready;
  return reg.pushManager.getSubscription();
}

/** Returns 'subscribed' | 'denied' | 'failed'. */
export async function subscribeTeam(team: string): Promise<'subscribed' | 'denied' | 'failed'> {
  try {
    const key = await serverPushKey();
    if (!key || !pushSupported()) return 'failed';
    const perm = await Notification.requestPermission();
    if (perm !== 'granted') return 'denied';
    const reg = await navigator.serviceWorker.ready;
    const sub =
      (await reg.pushManager.getSubscription()) ??
      (await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: b64ToUint8(key) as BufferSource }));
    const res = await fetch('/api/push/subscribe', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ subscription: sub.toJSON(), team }),
    });
    return res.ok ? 'subscribed' : 'failed';
  } catch {
    return 'failed';
  }
}

export async function unsubscribePush(): Promise<void> {
  try {
    const sub = await currentSubscription();
    if (!sub) return;
    await fetch('/api/push/unsubscribe', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ endpoint: sub.endpoint }),
    });
    await sub.unsubscribe();
  } catch { /* best effort */ }
}
