import { useCallback, useRef, useState } from 'react';
import { useQuery } from 'react-query';

import {
  getFeedNotificationConfiguration,
  getDisabledModules,
  getModulesPreferences,
} from './services';
import {
  FeedNotificationConfigurationMode,
  type GetFeedNotificationConfigurationResponse,
  type GetModulesPreferencesResponse,
  type UseNotificationsBellOpenStateOptions,
} from './types';

import { type NotificationModuleCodes } from './constants';
import { notificationsKeys } from './queries';
import { mergeModulesConfig } from './utils';

/**
 * Custom hook that throttles function calls to prevent excessive execution.
 * Unlike debounce, throttle ensures the function is called at regular intervals.
 *
 * @param callback - The function to throttle
 * @param delay - The delay in milliseconds between allowed executions
 * @returns A throttled version of the callback function
 */
export const useThrottle = <T extends (...args: any[]) => any>(
  callback: T,
  delay: number = 1000,
): T => {
  const lastExecuted = useRef<number>(0);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  const throttledCallback = useCallback(
    (...args: Parameters<T>) => {
      const now = Date.now();
      const timeSinceLastExecution = now - lastExecuted.current;

      // Clear any existing timeout
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }

      if (timeSinceLastExecution >= delay) {
        // Execute immediately if enough time has passed
        lastExecuted.current = now;
        callback(...args);
      } else {
        // Schedule execution for the remaining time
        const remainingTime = delay - timeSinceLastExecution;
        timeoutRef.current = setTimeout(() => {
          lastExecuted.current = Date.now();
          callback(...args);
        }, remainingTime);
      }
    },
    [callback, delay],
  ) as T;

  return throttledCallback;
};

const BELL_BURST_WINDOW_MS = 500;

/**
 * Manages open state for the notifications panel with burst-click handling:
 * rapid clicks within the burst window are treated as "open once" (no toggle),
 * avoiding flicker and extra API calls.
 */
export const useNotificationsBellOpenState = (
  initialOpen: boolean,
  options?: UseNotificationsBellOpenStateOptions,
) => {
  const [isOpen, setOpen] = useState(initialOpen);
  const lastClickTimeRef = useRef(0);
  const onBeforeToggle = options?.onBeforeToggle ?? (() => undefined);

  const handleToggleClick = useCallback(() => {
    onBeforeToggle();
    const now = Date.now();
    const isRapidClick = now - lastClickTimeRef.current < BELL_BURST_WINDOW_MS;
    lastClickTimeRef.current = now;

    if (isRapidClick) {
      setOpen(true);
    } else {
      setOpen(prev => !prev);
    }
  }, [onBeforeToggle]);

  return [isOpen, handleToggleClick, setOpen] as const;
};

export const useNotificationsConfigPageQueries = () => {
  const { data: modulesPreferences, isLoading: isLoadingModulesPreferences } =
    useQuery(
      notificationsKeys.getModulesPreferences(),
      () => getModulesPreferences(),
      {
        select: (response: { data: GetModulesPreferencesResponse }) =>
          mergeModulesConfig(response.data.modules),
      },
    );

  const { data: disabledModules, isLoading: isLoadingDisabledModules } =
    useQuery(
      notificationsKeys.getDisabledModules(),
      () => getDisabledModules(),
      {
        select: (response: { data: NotificationModuleCodes[] }) =>
          response.data,
      },
    );

  const {
    data: feedEmailNotificationsEnabled,
    isLoading: isLoadingFeedEmailNotificationsEnabled,
  } = useQuery(
    notificationsKeys.getFeedEmailNotificationConfiguration(),
    () =>
      getFeedNotificationConfiguration(FeedNotificationConfigurationMode.EMAIL),
    {
      select: (response: { data: GetFeedNotificationConfigurationResponse }) =>
        response.data.configs.find(
          config => config.mode === FeedNotificationConfigurationMode.EMAIL,
        )?.enabled ?? false,
    },
  );

  return {
    isLoading:
      isLoadingModulesPreferences ||
      isLoadingDisabledModules ||
      isLoadingFeedEmailNotificationsEnabled,
    modulesPreferences,
    disabledModules,
    feedEmailNotificationsEnabled,
  };
};
