'use client'

import { useEffect, useRef, useState } from 'react'
import { ChevronDown, Loader2, LogOut, UserRound } from 'lucide-react'
import { clear as idbClear } from 'idb-keyval'
import { logout } from '@/app/actions'

// Everything this device is holding on the signed-in account's behalf.
//
// Dropping the cookie is not enough on a shared iPad: the push subscription
// would keep ringing with the previous person's reminders, the IndexedDB
// thoughts cache renders instantly on the next visit (before any fetch can
// replace it), and the service worker's response cache would serve their pages
// outright while offline. Each step is best-effort — a device that cannot clear
// its cache must still be able to sign out.
async function wipeLocalState() {
  // `serviceWorker.ready` never settles when no worker is registered, so race
  // it rather than hang the sign-out on a browser where registration failed.
  const ready = (): Promise<ServiceWorkerRegistration | null> =>
    Promise.race([
      navigator.serviceWorker.ready,
      new Promise<null>(r => setTimeout(() => r(null), 2000)),
    ])

  try {
    if ('serviceWorker' in navigator) {
      const reg = await ready()
      const sub = await reg?.pushManager?.getSubscription().catch(() => null)
      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(() => {})
      }
    }
  } catch { /* best effort */ }

  try { await idbClear() } catch { /* best effort */ }
  try {
    if ('caches' in window) {
      const keys = await caches.keys()
      await Promise.all(keys.map(k => caches.delete(k)))
    }
  } catch { /* best effort */ }
}

// The dashboard's identity block, doubling as the account menu.
//
// Sessions last 400 days — right on a personal phone, wrong on a shared iPad,
// where the only way to hand the device to someone else was to clear the
// browser's cookies. This is the way out: tap your own name, sign out, and the
// next person logs in as themselves.
export function AccountMenu({ name, email }: { name: string; email: string }) {
  const [open, setOpen] = useState(false)
  const [signingOut, setSigningOut] = useState(false)
  const wrapRef = useRef<HTMLDivElement>(null)

  // Close on an outside tap or Escape. Pointerdown rather than click so the
  // menu is already gone by the time a tap lands on whatever is underneath.
  useEffect(() => {
    if (!open) return
    const onDown = (e: PointerEvent) => {
      if (!wrapRef.current?.contains(e.target as Node)) setOpen(false)
    }
    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) }
    document.addEventListener('pointerdown', onDown)
    document.addEventListener('keydown', onKey)
    return () => {
      document.removeEventListener('pointerdown', onDown)
      document.removeEventListener('keydown', onKey)
    }
  }, [open])

  const signOut = async () => {
    if (signingOut) return
    setSigningOut(true)
    await wipeLocalState()
    // Clears the cookie server-side and redirects to /login.
    await logout()
  }

  return (
    <div ref={wrapRef} className="relative">
      <button
        onClick={() => setOpen(o => !o)}
        className="text-left rounded-lg px-1 -mx-1 py-0.5 hover:bg-muted"
        aria-haspopup="menu"
        aria-expanded={open}
        aria-label="Account"
      >
        <div className="font-semibold tracking-tight leading-none">Steward</div>
        <div className="text-xs text-muted-foreground flex items-center gap-0.5">
          Hi {name} 👋
          <ChevronDown className={`h-3 w-3 transition-transform ${open ? 'rotate-180' : ''}`} />
        </div>
      </button>

      {open && (
        <div
          role="menu"
          className="absolute left-0 top-full mt-2 z-50 w-56 rounded-xl border border-border bg-card shadow-lg overflow-hidden"
        >
          <div className="px-3 py-2.5 border-b border-border flex items-start gap-2">
            <UserRound className="h-4 w-4 mt-0.5 text-muted-foreground shrink-0" />
            <div className="min-w-0">
              <div className="text-sm font-medium leading-tight">{name}</div>
              <div className="text-xs text-muted-foreground break-words">{email}</div>
            </div>
          </div>
          <button
            type="button"
            role="menuitem"
            onClick={signOut}
            disabled={signingOut}
            className="w-full px-3 py-2.5 text-sm text-left flex items-center gap-2 hover:bg-muted disabled:opacity-60"
          >
            {signingOut
              ? <Loader2 className="h-4 w-4 text-muted-foreground animate-spin" />
              : <LogOut className="h-4 w-4 text-muted-foreground" />}
            {signingOut ? 'Signing out…' : 'Sign out'}
          </button>
        </div>
      )}
    </div>
  )
}
