import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useEffect, useRef, useState } from 'react'
import { Bell, CheckCheck } from 'lucide-react'
import { useNavigate } from 'react-router-dom'
import { toast } from 'sonner'
import { api } from '@/lib/api'
import { ensureConnection } from '@/lib/realtime'
import { useAuth } from '@/contexts/AuthContext'
import { cn } from '@/lib/cn'

type NotificationDto = {
  id: string
  type: number
  title: string
  description: string | null
  href: string | null
  refId: string | null
  createdAt: string
  readAt: string | null
}

const fmtWhen = (iso: string) => {
  const diff = Date.now() - new Date(iso).getTime()
  const mins = Math.floor(diff / 60_000)
  if (mins < 1) return 'vừa xong'
  if (mins < 60) return `${mins}p trước`
  const hrs = Math.floor(mins / 60)
  if (hrs < 24) return `${hrs}h trước`
  const days = Math.floor(hrs / 24)
  return `${days}d trước`
}

export function NotificationBell() {
  const [open, setOpen] = useState(false)
  const panelRef = useRef<HTMLDivElement>(null)
  const navigate = useNavigate()
  const qc = useQueryClient()
  const { isAuthenticated } = useAuth()

  const list = useQuery({
    queryKey: ['notifications'],
    queryFn: async () => (await api.get<NotificationDto[]>('/notifications', { params: { limit: 20 } })).data,
    // Fallback polling at 60s in case SignalR disconnects + reconnect fails
    refetchInterval: 60_000,
  })

  // Subscribe realtime when authenticated. Toast on push + invalidate query.
  useEffect(() => {
    if (!isAuthenticated) return
    let conn: Awaited<ReturnType<typeof ensureConnection>> | null = null
    let cancelled = false

    const handler = (payload: NotificationDto) => {
      qc.invalidateQueries({ queryKey: ['notifications'] })
      toast.message(payload.title, { description: payload.description ?? undefined })
    }

    ensureConnection()
      .then(c => {
        if (cancelled) return
        conn = c
        c.on('notification-created', handler)
      })
      .catch(() => {
        // SignalR unavailable — rely on polling fallback
      })

    return () => {
      cancelled = true
      if (conn) conn.off('notification-created', handler)
    }
  }, [isAuthenticated, qc])

  const items = list.data ?? []
  const unread = items.filter(n => !n.readAt).length

  const markRead = useMutation({
    mutationFn: async (id: string) => api.post(`/notifications/${id}/read`),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['notifications'] }),
  })

  const markAllRead = useMutation({
    mutationFn: async () => api.post('/notifications/read-all'),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['notifications'] }),
  })

  useEffect(() => {
    if (!open) return
    const close = (e: MouseEvent) => {
      if (panelRef.current && !panelRef.current.contains(e.target as Node)) setOpen(false)
    }
    document.addEventListener('mousedown', close)
    return () => document.removeEventListener('mousedown', close)
  }, [open])

  return (
    <div className="relative" ref={panelRef}>
      <button
        onClick={() => setOpen(o => !o)}
        className="relative flex h-9 w-9 items-center justify-center rounded-md text-slate-600 transition hover:bg-slate-100 hover:text-slate-900"
        aria-label="Thông báo"
      >
        <Bell className="h-4 w-4" />
        {unread > 0 && (
          <span className="absolute -right-0.5 -top-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white">
            {unread > 99 ? '99+' : unread}
          </span>
        )}
      </button>

      {open && (
        <div className="absolute right-0 z-50 mt-2 w-80 overflow-hidden rounded-lg border border-slate-200 bg-white shadow-lg">
          <div className="flex items-center justify-between border-b border-slate-100 px-4 py-2.5">
            <div>
              <div className="text-sm font-semibold text-slate-700">Thông báo</div>
              <div className="text-xs text-slate-400">{unread > 0 ? `${unread} chưa đọc` : 'Đã đọc hết'}</div>
            </div>
            {unread > 0 && (
              <button
                onClick={() => markAllRead.mutate()}
                disabled={markAllRead.isPending}
                className="flex items-center gap-1 rounded-md px-2 py-1 text-xs text-brand-600 transition hover:bg-brand-50"
                title="Đánh dấu tất cả đã đọc"
              >
                <CheckCheck className="h-3.5 w-3.5" />
                Đọc hết
              </button>
            )}
          </div>
          <div className="max-h-96 overflow-y-auto">
            {items.length === 0 && (
              <div className="px-4 py-10 text-center text-xs text-slate-400">Không có thông báo nào.</div>
            )}
            {items.map(n => (
              <button
                key={n.id}
                onClick={() => {
                  if (!n.readAt) markRead.mutate(n.id)
                  if (n.href) navigate(n.href)
                  setOpen(false)
                }}
                className={cn(
                  'block w-full border-b border-slate-50 px-4 py-3 text-left transition hover:bg-slate-50',
                  !n.readAt && 'bg-brand-50/30',
                )}
              >
                <div className="flex items-start justify-between gap-2">
                  <div className="min-w-0 flex-1">
                    <div className="truncate text-sm font-medium text-slate-700">{n.title}</div>
                    {n.description && <div className="truncate text-xs text-slate-400">{n.description}</div>}
                  </div>
                  <div className="shrink-0 text-[10px] text-slate-400">{fmtWhen(n.createdAt)}</div>
                </div>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  )
}
