import { useEffect, useRef, useCallback } from 'react';
import { toast } from 'sonner';
import { Check, X, Bell, UserPlus } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';
import { useNotifications } from '@/hooks/useNotifications';
import { useConnections } from '@/hooks/useConnections';
import { getErrorMessage } from '@/lib/api';
import type { AppNotification } from '@/types';

export default function NotificationToaster() {
  const { notifications, unreadCount } = useNotifications();
  const { respond } = useConnections();
  const queryClient = useQueryClient();
  const maxSeenIdRef = useRef(0);
  const initializedRef = useRef(false);
  const prevUnreadRef = useRef(0);
  // Track in-flight request IDs so repeated clicks are blocked
  const respondingRef = useRef<Set<number>>(new Set());
  // Always call the latest respond — Sonner toasts capture closures at creation time
  const respondRef = useRef(respond);
  respondRef.current = respond;

  const handleConnectionRespond = useCallback(
    async (requestId: number, action: 'accept' | 'reject', toastId: string | number) => {
      // Guard against double-clicks (Sonner toasts are static, no disabled prop)
      if (respondingRef.current.has(requestId)) return;
      respondingRef.current.add(requestId);

      // Immediately dismiss the custom toast and show a loading indicator
      toast.dismiss(toastId);
      const loadingId = toast.loading(
        action === 'accept' ? 'Accepting connection…' : 'Declining request…',
      );

      try {
        await respondRef.current({ requestId, action });
        toast.dismiss(loadingId);
        toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined');
      } catch (err: any) {
        toast.dismiss(loadingId);
        // 409 means the request was already resolved (e.g. accepted via notification center)
        const status = err?.response?.status;
        if (status === 409) {
          toast.success(action === 'accept' ? 'Connection already accepted' : 'Request already resolved');
        } else {
          toast.error(getErrorMessage(err, 'Failed to respond to request'));
        }
      } finally {
        respondingRef.current.delete(requestId);
      }
    },
    [],
  );

  // Track unread count changes to force-refetch the list
  useEffect(() => {
    if (unreadCount > prevUnreadRef.current && initializedRef.current) {
      queryClient.invalidateQueries({ queryKey: ['notifications', 'list'] });
    }
    prevUnreadRef.current = unreadCount;
  }, [unreadCount, queryClient]);

  // Show toasts for new notifications (ID > max seen)
  useEffect(() => {
    if (!notifications.length) return;

    // On first load, record the max ID without toasting
    if (!initializedRef.current) {
      maxSeenIdRef.current = Math.max(...notifications.map((n) => n.id));
      initializedRef.current = true;
      return;
    }

    // Find unread notifications with IDs higher than our watermark
    const newNotifications = notifications.filter(
      (n) => !n.is_read && n.id > maxSeenIdRef.current,
    );

    // Advance watermark
    const maxCurrent = Math.max(...notifications.map((n) => n.id));
    if (maxCurrent > maxSeenIdRef.current) {
      maxSeenIdRef.current = maxCurrent;
    }

    // Eagerly refresh incoming requests when connection_request notifications arrive
    // so accept buttons work immediately on NotificationsPage / PeoplePage
    if (newNotifications.some((n) => n.type === 'connection_request')) {
      queryClient.invalidateQueries({ queryKey: ['connections', 'incoming'] });
    }

    // Show toasts
    newNotifications.forEach((notification) => {
      if (notification.type === 'connection_request' && notification.source_id) {
        showConnectionRequestToast(notification);
      } else {
        toast(notification.title || 'New Notification', {
          description: notification.message || undefined,
          icon: <Bell className="h-4 w-4" />,
          duration: 8000,
        });
      }
    });
  }, [notifications, handleConnectionRespond]);

  const showConnectionRequestToast = (notification: AppNotification) => {
    const requestId = notification.source_id!;

    toast.custom(
      (id) => (
        <div className="w-[356px] rounded-lg border border-border bg-card p-4 shadow-lg">
          <div className="flex items-start gap-3">
            <div className="h-9 w-9 rounded-full bg-violet-500/15 flex items-center justify-center shrink-0">
              <UserPlus className="h-4 w-4 text-violet-400" />
            </div>
            <div className="flex-1 min-w-0">
              <p className="text-sm font-medium text-foreground">Connection Request</p>
              <p className="text-xs text-muted-foreground mt-0.5">
                {notification.message || 'Someone wants to connect with you'}
              </p>
              <div className="flex items-center gap-2 mt-3">
                <button
                  onClick={() => handleConnectionRespond(requestId, 'accept', id)}
                  className="flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-md bg-accent text-accent-foreground hover:bg-accent/90 transition-colors"
                >
                  <Check className="h-3.5 w-3.5" />
                  Accept
                </button>
                <button
                  onClick={() => handleConnectionRespond(requestId, 'reject', id)}
                  className="flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-md text-muted-foreground hover:bg-card-elevated transition-colors"
                >
                  <X className="h-3.5 w-3.5" />
                  Reject
                </button>
              </div>
            </div>
          </div>
        </div>
      ),
      { id: `connection-request-${requestId}`, duration: 30000 },
    );
  };

  return null;
}
