import { useState, useRef, useEffect } from 'react'
import { createPortal } from 'react-dom'
import { useNavigate } from 'react-router-dom'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
  Bell, Send, PlayCircle, CheckCircle, XCircle, Image, AlertTriangle, X,
} from 'lucide-react'
import { clsx } from 'clsx'
import {
  getNotifications, getUnreadCount, markAsRead, markOneAsRead,
  type Notification,
} from '../../api/notifications'

const ACTION_CONFIG: Record<string, { icon: typeof Bell; label: (d: Record<string, unknown> | null) => string; color: string }> = {
  'order.submitted': {
    icon: Send,
    label: (d) => `Order ${d?.order_number ?? '?'} submitted`,
    color: 'text-blue-500',
  },
  'order.processing': {
    icon: PlayCircle,
    label: (d) => `Order ${d?.order_number ?? '?'} is processing`,
    color: 'text-yellow-500',
  },
  'order.completed': {
    icon: CheckCircle,
    label: (d) => `Order ${d?.order_number ?? '?'} completed`,
    color: 'text-status-success-text',
  },
  'order.rejected': {
    icon: XCircle,
    label: (d) => `Order ${d?.order_number ?? '?'} was rejected`,
    color: 'text-red-500',
  },
  'render.completed': {
    icon: Image,
    label: (d) => `Render done: ${d?.product_name ?? 'unknown'} — ${d?.output_type ?? ''}`,
    color: 'text-status-success-text',
  },
  'render.failed': {
    icon: AlertTriangle,
    label: (d) => `Render failed: ${d?.product_name ?? 'unknown'} — ${d?.output_type ?? ''}`,
    color: 'text-red-500',
  },
  'excel.import_warnings': {
    icon: AlertTriangle,
    label: (d) => `Excel '${d?.filename ?? '?'}' had ${d?.warning_count ?? '?'} warning(s)`,
    color: 'text-amber-500',
  },
  'excel.import_error': {
    icon: XCircle,
    label: (d) => `Excel parse failed: ${d?.filename ?? '?'}`,
    color: 'text-red-500',
  },
  'excel.finalize_error': {
    icon: XCircle,
    label: (d) => `Order creation failed: ${d?.filename ?? '?'}`,
    color: 'text-red-500',
  },
}

function relativeTime(ts: string): string {
  const diff = Date.now() - new Date(ts).getTime()
  const seconds = Math.floor(diff / 1000)
  if (seconds < 60) return 'just now'
  const minutes = Math.floor(seconds / 60)
  if (minutes < 60) return `${minutes}m ago`
  const hours = Math.floor(minutes / 60)
  if (hours < 24) return `${hours}h ago`
  const days = Math.floor(hours / 24)
  return `${days}d ago`
}

export default function NotificationCenter() {
  const [open, setOpen] = useState(false)
  const bellRef = useRef<HTMLButtonElement>(null)
  const dropdownRef = useRef<HTMLDivElement>(null)
  const navigate = useNavigate()
  const qc = useQueryClient()

  const { data: unreadCount = 0 } = useQuery({
    queryKey: ['notifications', 'unread-count'],
    queryFn: getUnreadCount,
    refetchInterval: 60_000,
    staleTime: 5_000,
  })

  const { data } = useQuery({
    queryKey: ['notifications', 'list'],
    queryFn: () => getNotifications({ limit: 20 }),
    enabled: open,
    staleTime: 5_000,
  })

  const markAllMutation = useMutation({
    mutationFn: () => markAsRead(),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['notifications'] })
    },
  })

  const markOneMutation = useMutation({
    mutationFn: (id: string) => markOneAsRead(id),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['notifications'] })
    },
  })

  // Click-outside to close
  useEffect(() => {
    if (!open) return
    function handleClick(e: MouseEvent) {
      if (
        dropdownRef.current && !dropdownRef.current.contains(e.target as Node) &&
        bellRef.current && !bellRef.current.contains(e.target as Node)
      ) {
        setOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClick)
    return () => document.removeEventListener('mousedown', handleClick)
  }, [open])

  function handleNotificationClick(n: Notification) {
    if (!n.read_at) markOneMutation.mutate(n.id)
    if (n.entity_type === 'order' && n.entity_id) {
      navigate(`/orders/${n.entity_id}`)
    }
    setOpen(false)
  }

  // Position dropdown relative to bell button
  const bellRect = bellRef.current?.getBoundingClientRect()

  return (
    <>
      <button
        ref={bellRef}
        onClick={() => setOpen((v) => !v)}
        className="relative p-1.5 rounded-md hover:bg-surface-hover transition-colors"
        title="Notifications"
      >
        <Bell size={18} className="text-content-secondary" />
        {unreadCount > 0 && (
          <span className="absolute -top-0.5 -right-0.5 min-w-[16px] h-4 px-1 flex items-center justify-center rounded-full bg-red-500 text-white text-[10px] font-bold leading-none">
            {unreadCount > 99 ? '99+' : unreadCount}
          </span>
        )}
      </button>

      {open && bellRect && createPortal(
        <div
          ref={dropdownRef}
          className="fixed z-[9999] w-80 max-h-[28rem] rounded-lg shadow-xl border flex flex-col"
          style={{
            top: bellRect.bottom + 6,
            left: Math.max(8, bellRect.left - 240),
            backgroundColor: 'var(--color-bg-surface)',
            borderColor: 'var(--color-border)',
          }}
        >
          {/* Header */}
          <div className="flex items-center justify-between px-4 py-2.5 border-b border-border-light">
            <span className="text-sm font-semibold text-content">Notifications</span>
            <div className="flex items-center gap-2">
              {unreadCount > 0 && (
                <button
                  onClick={() => markAllMutation.mutate()}
                  className="text-xs text-accent hover:underline"
                >
                  Mark all as read
                </button>
              )}
              <button onClick={() => setOpen(false)} className="p-0.5 hover:bg-surface-hover rounded" title="Close notifications">
                <X size={14} className="text-content-muted" />
              </button>
            </div>
          </div>

          {/* List */}
          <div className="flex-1 overflow-y-auto">
            {!data?.items.length && (
              <div className="py-8 text-center text-sm text-content-muted">No notifications</div>
            )}
            {data?.items.map((n) => {
              const cfg = ACTION_CONFIG[n.action] ?? {
                icon: Bell,
                label: () => n.action,
                color: 'text-content-secondary',
              }
              const Icon = cfg.icon
              return (
                <button
                  key={n.id}
                  onClick={() => handleNotificationClick(n)}
                  className={clsx(
                    'w-full flex items-start gap-3 px-4 py-3 text-left hover:bg-surface-hover transition-colors border-b border-border-light',
                    !n.read_at && 'bg-status-info-bg',
                  )}
                >
                  <Icon size={16} className={clsx('mt-0.5 shrink-0', cfg.color)} />
                  <div className="flex-1 min-w-0">
                    <p className={clsx('text-sm', !n.read_at ? 'font-medium text-content' : 'text-content-secondary')}>
                      {cfg.label(n.details)}
                    </p>
                    {!!n.details?.error && (
                      <p className="mt-1 text-xs text-red-600 font-mono bg-red-50 rounded px-1.5 py-0.5 truncate">
                        {String(n.details.error)}
                      </p>
                    )}
                    <p className="text-xs text-content-muted mt-0.5">{relativeTime(n.timestamp)}</p>
                  </div>
                  {!n.read_at && (
                    <span className="mt-1.5 w-2 h-2 rounded-full bg-blue-500 shrink-0" />
                  )}
                </button>
              )
            })}
          </div>

          {/* Footer */}
          <div className="px-4 py-2 border-t border-border-light text-center">
            <button
              onClick={() => { navigate('/notifications'); setOpen(false) }}
              className="text-xs text-accent hover:underline"
            >
              View all notifications
            </button>
          </div>
        </div>,
        document.body,
      )}
    </>
  )
}
