import { useMutation, useQueryClient, type QueryKey } from '@tanstack/react-query';
import type { Paginated } from '@/lib/api/types';
import { notificationKeys } from '../keys';
import { notificationsApi } from '../apis';
import type { AppNotification } from '../types';

interface MarkReadContext {
  prevCount?: number;
  prevLists: Array<[QueryKey, Paginated<AppNotification> | undefined]>;
}

/**
 * Mark one notification read — **optimistic** (phase §3.4): flip `isRead` across every cached list page and
 * decrement the cached unread count at once (so the row de-emphasises and the bell badge drops instantly),
 * roll both back on error, and invalidate on settle (no full refetch on the happy path). The count only
 * decrements when the notification was actually unread, so re-opening a read one never underflows.
 */
export function useMarkNotificationRead() {
  const queryClient = useQueryClient();
  return useMutation<void, unknown, number, MarkReadContext>({
    mutationFn: (notificationId) => notificationsApi.markRead(notificationId),

    onMutate: async (notificationId) => {
      await queryClient.cancelQueries({ queryKey: notificationKeys.all });
      const prevCount = queryClient.getQueryData<number>(notificationKeys.unreadCount());
      const prevLists = queryClient.getQueriesData<Paginated<AppNotification>>({ queryKey: notificationKeys.lists() });

      const wasUnread = prevLists.some(([, data]) =>
        data?.items.some((n) => n.id === notificationId && !n.isRead),
      );

      queryClient.setQueriesData<Paginated<AppNotification>>({ queryKey: notificationKeys.lists() }, (data) =>
        data ? { ...data, items: data.items.map((n) => (n.id === notificationId ? { ...n, isRead: true } : n)) } : data,
      );
      if (wasUnread && typeof prevCount === 'number') {
        queryClient.setQueryData<number>(notificationKeys.unreadCount(), Math.max(0, prevCount - 1));
      }
      return { prevCount, prevLists };
    },

    onError: (_err, _id, context) => {
      if (context?.prevCount !== undefined) queryClient.setQueryData(notificationKeys.unreadCount(), context.prevCount);
      context?.prevLists.forEach(([key, data]) => queryClient.setQueryData(key, data));
    },

    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: notificationKeys.lists() });
      queryClient.invalidateQueries({ queryKey: notificationKeys.unreadCount() });
    },
  });
}
