import useDebounceCallback from './useDebounceCallback';

export type ThrottleOptions = {
  /**
   * Determines whether the function should be invoked on the leading edge of the timeout.
   * @default true
   */
  leading?: boolean;
  /**
   * Determines whether the function should be invoked on the trailing edge of the timeout.
   * @default true
   */
  trailing?: boolean;
};

/**
 * Custom hook that creates a throttled version of a callback function
 *
 * This is similar to a debounce, but will invoke the callback at a maximum
 * frequency rather than waiting for a lull in invocations.
 *
 * @param func - The function to throttle
 * @param wait - The throttle wait period in milliseconds (default: 500)
 * @param options - Throttle options (leading/trailing edge control)
 * @returns A throttled function with `cancel()` and `flush()` methods
 *
 * @remarks
 * Note: There is a known bug in lodash's throttle where a "leading edge"
 * invocation after a "trailing edge" may occur sooner than expected.
 *
 * This effectively invokes the new leading edge after the last invocation of
 * the wrapper rather than the last invocation of the underlying function.
 *
 * See: https://github.com/lodash/lodash/issues/3051
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- `any` used for proper generic type inference
export default function useThrottleCallback<T extends (...args: any[]) => any>(
  func: T,
  wait?: number,
  options?: ThrottleOptions
) {
  return useDebounceCallback(func, wait, {
    leading: true,
    trailing: true,
    maxWait: wait,
    ...options,
  });
}
