'use client'

import { useCallback, useEffect, useState } from 'react'
import { Bell, BellOff, BellRing } from 'lucide-react'

/**
 * Turn on Web Push for this device.
 *
 * iOS only grants notification permission from a real user gesture, and only
 * to a PWA launched from the Home Screen — so this is a button rather than
 * something that happens on load, and it says why when the browser cannot do
 * it at all rather than failing silently.
 */
function urlBase64ToUint8Array(base64: string): Uint8Array {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4)
  const raw = atob((base64 + padding).replace(/-/g, '+').replace(/_/g, '/'))
  return Uint8Array.from([...raw].map(c => c.charCodeAt(0)))
}

type State = 'unsupported' | 'needs-install' | 'off' | 'on' | 'blocked' | 'working'

export function PushToggle({ vapidPublicKey }: { vapidPublicKey: string }) {
  const [state, setState] = useState<State>('working')

  useEffect(() => {
    if (typeof window === 'undefined') return
    if (!('serviceWorker' in navigator) || !('PushManager' in window) || !('Notification' in window)) {
      // iOS exposes PushManager ONLY in an installed PWA, so a missing API on
      // an iPhone means "not installed yet", not "never going to work".
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
      setState(iOS ? 'needs-install' : 'unsupported')
      return
    }
    if (Notification.permission === 'denied') { setState('blocked'); return }
    navigator.serviceWorker.ready
      .then(reg => reg.pushManager.getSubscription())
      .then(sub => setState(sub ? 'on' : 'off'))
      .catch(() => setState('off'))
  }, [])

  const enable = useCallback(async () => {
    setState('working')
    try {
      const permission = await Notification.requestPermission()
      if (permission !== 'granted') { setState(permission === 'denied' ? 'blocked' : 'off'); return }
      const reg = await navigator.serviceWorker.ready
      const sub = await reg.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) as BufferSource,
      })
      const res = await fetch('/api/push/subscribe', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(sub.toJSON()),
      })
      setState(res.ok ? 'on' : 'off')
    } catch (e) {
      console.error('[push] enable failed', e)
      setState('off')
    }
  }, [vapidPublicKey])

  const disable = useCallback(async () => {
    setState('working')
    try {
      const reg = await navigator.serviceWorker.ready
      const sub = await reg.pushManager.getSubscription()
      if (sub) {
        await fetch('/api/push/subscribe', {
          method: 'DELETE',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ endpoint: sub.endpoint }),
        }).catch(() => {})
        await sub.unsubscribe().catch(() => {})
      }
    } finally {
      setState('off')
    }
  }, [])

  if (state === 'unsupported') return null
  if (state === 'needs-install') {
    return (
      <span className="p-2 text-muted-foreground" title="Add Steward to your Home Screen first — iOS only allows notifications for an installed app.">
        <BellOff className="h-4 w-4" />
      </span>
    )
  }
  if (state === 'blocked') {
    return (
      <span className="p-2 text-muted-foreground" title="Notifications are blocked for Steward in your system settings.">
        <BellOff className="h-4 w-4" />
      </span>
    )
  }
  return (
    <button
      onClick={state === 'on' ? disable : enable}
      disabled={state === 'working'}
      className={`p-2 rounded-lg hover:bg-muted ${state === 'on' ? 'text-primary' : 'text-muted-foreground'} disabled:opacity-50`}
      aria-label={state === 'on' ? 'Turn off notifications' : 'Turn on notifications'}
      title={state === 'on' ? 'Notifications on — tap to turn off' : 'Turn on notifications for this device'}
    >
      {state === 'on' ? <BellRing className="h-4 w-4" /> : <Bell className="h-4 w-4" />}
    </button>
  )
}
