"use client";

import { useCallback, useEffect } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";

import { useCurrentUser } from "@/features/auth/hook/use-current-user";

import {
  getSystemNotifications,
  type SystemNotification,
} from "./system-notifications-service";

export const SYSTEM_NOTIFICATIONS_QUERY_KEY = ["system-notifications"] as const;

/* How often we ask the server for new notifications. */
const REFRESH_INTERVAL_MS = 30_000;

/* How many unread notifications the dropdown shows at once. */
const NOTIFICATION_PAGE_SIZE = 20;

type UseSystemNotificationsResult = {
  notifications: SystemNotification[];
  unreadCount: number;
  isLoading: boolean;
  error: string | null;
  refetch: () => void;
};

/*
 * One shared source of unread notifications for the whole app.
 *
 * Every place that shows notifications (the header bell, the dropdown, and the
 * sidebar badges) calls this hook. They all share the same React Query key, so
 * no matter how many of them are on screen the app only makes one request per
 * refresh, and they always show the same number.
 *
 * Nothing is requested until we know who is logged in, so the login page and
 * the moments right after a page load stay quiet.
 */
export function useSystemNotifications(): UseSystemNotificationsResult {
  const queryClient = useQueryClient();
  const { user } = useCurrentUser();

  const isLoggedIn = Boolean(user?.id);

  const query = useQuery({
    queryKey: SYSTEM_NOTIFICATIONS_QUERY_KEY,
    queryFn: () =>
      getSystemNotifications({
        page: 1,
        limit: NOTIFICATION_PAGE_SIZE,
        isRead: false,
      }),
    enabled: isLoggedIn,
    refetchInterval: REFRESH_INTERVAL_MS,
    /*
     * The app turns this off for every query by default, but notifications
     * go stale while the tab sits in the background, so turn it back on here.
     */
    refetchOnWindowFocus: true,
  });

  /*
   * Reload as soon as something else on the page changes a notification,
   * for example after marking one as read.
   */
  useEffect(() => {
    if (!isLoggedIn) {
      return;
    }

    const handleNotificationUpdated = () => {
      void queryClient.invalidateQueries({
        queryKey: SYSTEM_NOTIFICATIONS_QUERY_KEY,
      });
    };

    window.addEventListener(
      "system-notification-updated",
      handleNotificationUpdated,
    );

    return () => {
      window.removeEventListener(
        "system-notification-updated",
        handleNotificationUpdated,
      );
    };
  }, [isLoggedIn, queryClient]);

  /*
   * Keep the same function between renders. Callers put this in effect
   * dependency lists, so a new function each render would loop forever.
   *
   * The logged-in check matters here: a manual refetch ignores the `enabled`
   * option above, so without it a logged-out user could still trigger a call.
   */
  const queryRefetch = query.refetch;

  const refetch = useCallback(() => {
    if (!isLoggedIn) {
      return;
    }

    void queryRefetch();
  }, [isLoggedIn, queryRefetch]);

  return {
    notifications: query.data?.data ?? [],
    unreadCount: Math.max(query.data?.meta.unreadCount ?? 0, 0),
    isLoading: query.isLoading,
    error: query.error
      ? query.error instanceof Error
        ? query.error.message
        : "Unable to load notifications."
      : null,
    refetch,
  };
}
