'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import { Bell, CheckCheck } from 'lucide-react'
import { Button } from '@/components/ui/Button'
import { useBusiness } from '@/components/providers/BusinessProvider'
import {
  getNotifications,
  markAllNotificationsRead,
  markNotificationRead,
  type NotificationRecord,
} from '@/lib/api/agent'
import { formatRelativeTime } from '@/lib/types'
import { cn } from '@/lib/utils'

const LINKED_ALERT_TYPES = new Set(['low_stock', 'out_of_stock'])

function hrefFor(notification: NotificationRecord): string | null {
  if (LINKED_ALERT_TYPES.has(notification.type)) return '/dashboard/inventory'
  return null
}

export function NotificationBell() {
  const { business } = useBusiness()
  const [notifications, setNotifications] = useState<NotificationRecord[]>([])
  const [unreadCount, setUnreadCount] = useState(0)
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(true)
  const containerRef = useRef<HTMLDivElement>(null)

  const load = useCallback(async () => {
    if (!business?.businessId) return
    try {
      const res = await getNotifications({ limit: 20 })
      if (res.success) {
        setNotifications(res.data.notifications)
        setUnreadCount(res.data.unreadCount)
      }
    } catch {
      // polling will retry
    } finally {
      setLoading(false)
    }
  }, [business?.businessId])

  useEffect(() => {
    load()
    const interval = setInterval(load, 10000)
    return () => clearInterval(interval)
  }, [load])

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
        setOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  async function handleMarkRead(notification: NotificationRecord) {
    if (notification.read_at) return
    setNotifications(prev =>
      prev.map(n => (n.id === notification.id ? { ...n, read_at: new Date().toISOString() } : n))
    )
    setUnreadCount(count => Math.max(0, count - 1))
    await markNotificationRead(notification.id)
  }

  async function handleMarkAllRead() {
    setNotifications(prev => prev.map(n => ({ ...n, read_at: n.read_at || new Date().toISOString() })))
    setUnreadCount(0)
    await markAllNotificationsRead()
  }

  return (
    <div className="relative" ref={containerRef}>
      <Button variant="ghost" size="sm" onClick={() => setOpen(!open)} aria-label="Notifications" className="relative">
        <Bell className="h-5 w-5" />
        {unreadCount > 0 && (
          <span className="absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-semibold text-white">
            {unreadCount > 9 ? '9+' : unreadCount}
          </span>
        )}
      </Button>

      {open && (
        <div className="absolute right-0 mt-2 w-80 rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800">
          <div className="flex items-center justify-between border-b border-gray-200 px-4 py-2 dark:border-gray-700">
            <p className="text-sm font-semibold text-gray-900 dark:text-white">Notifications</p>
            {unreadCount > 0 && (
              <Button variant="ghost" size="sm" onClick={handleMarkAllRead} className="gap-1 text-xs">
                <CheckCheck className="h-3.5 w-3.5" />
                Mark all read
              </Button>
            )}
          </div>
          <div className="max-h-80 overflow-y-auto">
            {loading ? (
              <p className="px-4 py-6 text-center text-sm text-gray-500">Loading…</p>
            ) : notifications.length === 0 ? (
              <p className="px-4 py-6 text-center text-sm text-gray-500">No notifications yet</p>
            ) : (
              notifications.map(n => {
                const href = hrefFor(n)
                const inner = (
                  <div className="flex items-start gap-2">
                    {!n.read_at && <span className="mt-1.5 h-2 w-2 shrink-0 rounded-full bg-indigo-500" />}
                    <div className="min-w-0">
                      <p
                        className={cn(
                          'text-sm break-words',
                          n.read_at ? 'text-gray-600 dark:text-gray-400' : 'font-medium text-gray-900 dark:text-white'
                        )}
                      >
                        {n.message}
                      </p>
                      <p className="mt-0.5 text-xs text-gray-400">{formatRelativeTime(n.created_at)}</p>
                    </div>
                  </div>
                )
                const rowClass = cn(
                  'block w-full border-b border-gray-100 px-4 py-3 text-left transition-colors last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-700/50',
                  !n.read_at && 'bg-indigo-50/60 dark:bg-indigo-900/20'
                )
                return href ? (
                  <a
                    key={n.id}
                    href={href}
                    onClick={() => {
                      setOpen(false)
                      void handleMarkRead(n)
                    }}
                    className={cn(rowClass, 'cursor-pointer underline-offset-2 hover:underline')}
                  >
                    {inner}
                  </a>
                ) : (
                  <button key={n.id} type="button" onClick={() => handleMarkRead(n)} className={rowClass}>
                    {inner}
                  </button>
                )
              })
            )}
          </div>
        </div>
      )}
    </div>
  )
}
