/**
 * Push subscription manager.
 * Handles requesting notification permission, subscribing to push,
 * and syncing the subscription with the backend.
 */

async function fetchVapidPublicKey(): Promise<string | null> {
  try {
    const res = await fetch('/api/push-vapid-key')
    if (!res.ok) return null
    const data = await res.json()
    return data.public_key || null
  } catch {
    return null
  }
}

function urlBase64ToUint8Array(base64String: string): Uint8Array {
  const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
  const rawData = window.atob(base64)
  return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)))
}

/**
 * Request notification permission and subscribe to push notifications.
 * Posts the subscription to the backend, including the user's timezone.
 * Returns true if subscription was successfully registered.
 */
export async function subscribeToPush(): Promise<boolean> {
  if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
    return false
  }

  try {
    const permission = await Notification.requestPermission()
    if (permission !== 'granted') {
      return false
    }

    const vapidKey = await fetchVapidPublicKey()
    if (!vapidKey) {
      console.warn('[Push] VAPID public key not available; skipping subscription')
      return false
    }

    const registration = await navigator.serviceWorker.ready
    const subscription = await registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(vapidKey),
    })

    const subJson = subscription.toJSON()
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone

    const res = await fetch('/api/push-subscription', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        endpoint: subJson.endpoint,
        keys: subJson.keys,
        timezone,
      }),
    })

    return res.ok
  } catch (err) {
    console.warn('[Push] Failed to subscribe:', err)
    return false
  }
}

/**
 * Unsubscribe from push notifications and remove the subscription from the backend.
 */
export async function unsubscribeFromPush(): Promise<void> {
  if (!('serviceWorker' in navigator) || !('PushManager' in window)) return

  try {
    const registration = await navigator.serviceWorker.ready
    const subscription = await registration.pushManager.getSubscription()
    if (!subscription) return

    const endpoint = subscription.endpoint
    await subscription.unsubscribe()

    await fetch('/api/push-subscription', {
      method: 'DELETE',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ endpoint }),
    })
  } catch (err) {
    console.warn('[Push] Failed to unsubscribe:', err)
  }
}

/**
 * Check the current push permission state without prompting.
 */
export function getPushPermissionState(): NotificationPermission | 'unsupported' {
  if (!('Notification' in window)) return 'unsupported'
  return Notification.permission
}
