/**
 * WEB-PUSH (PWA-Benachrichtigungen) — Client-Seite.
 * Registriert den Service Worker (push-only) und verwaltet das Abo gegen /push/*.
 */
import { API_BASE_URL } from './api/client'

export function isPushSupported(): boolean {
  return (
    typeof navigator !== 'undefined' &&
    'serviceWorker' in navigator &&
    typeof window !== 'undefined' &&
    'PushManager' in window &&
    'Notification' in window
  )
}

/** Server-Status: ist Push konfiguriert + welcher VAPID-Public-Key. */
export async function fetchPushConfig(): Promise<{ enabled: boolean; publicKey: string | null }> {
  try {
    const r = await fetch(`${API_BASE_URL}/push/vapid-public-key`)
    if (!r.ok) return { enabled: false, publicKey: null }
    return await r.json()
  } catch {
    return { enabled: false, publicKey: null }
  }
}

function urlBase64ToUint8Array(base64: string): Uint8Array<ArrayBuffer> {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4)
  const b64 = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/')
  const raw = atob(b64)
  const arr = new Uint8Array(raw.length)
  for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i)
  return arr
}

export async function isSubscribed(): Promise<boolean> {
  if (!isPushSupported()) return false
  const reg = await navigator.serviceWorker.getRegistration()
  const sub = await reg?.pushManager.getSubscription()
  return !!sub
}

export type EnableResult = 'enabled' | 'denied' | 'unavailable'

export async function enablePush(): Promise<EnableResult> {
  if (!isPushSupported()) return 'unavailable'
  const cfg = await fetchPushConfig()
  if (!cfg.enabled || !cfg.publicKey) return 'unavailable'
  const permission = await Notification.requestPermission()
  if (permission !== 'granted') return 'denied'

  const reg = await navigator.serviceWorker.register('/sw.js')
  await navigator.serviceWorker.ready
  const sub = await reg.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(cfg.publicKey),
  })
  const json = sub.toJSON()
  await fetch(`${API_BASE_URL}/push/subscribe`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      endpoint: sub.endpoint,
      p256dh: json.keys?.p256dh ?? '',
      auth: json.keys?.auth ?? '',
    }),
  })
  return 'enabled'
}

export async function disablePush(): Promise<void> {
  if (!isPushSupported()) return
  const reg = await navigator.serviceWorker.getRegistration()
  const sub = await reg?.pushManager.getSubscription()
  if (!sub) return
  try {
    await fetch(`${API_BASE_URL}/push/unsubscribe`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ endpoint: sub.endpoint }),
    })
  } catch {
    /* trotzdem lokal abmelden */
  }
  await sub.unsubscribe()
}
