export function createDebouncedCallback<T extends unknown[]>(
  callback: (...args: T) => void,
  delayMs = 120,
) {
  let timerId = 0;
  let lastArgs: T | null = null;

  const run = () => {
    timerId = 0;
    if (!lastArgs) {
      return;
    }
    const args = lastArgs;
    lastArgs = null;
    callback(...args);
  };

  const debounced = (...args: T) => {
    lastArgs = args;
    if (timerId) {
      window.clearTimeout(timerId);
    }
    timerId = window.setTimeout(run, Math.max(0, Number(delayMs) || 0));
  };

  debounced.flush = () => {
    if (timerId) {
      window.clearTimeout(timerId);
      run();
      return true;
    }
    return false;
  };

  debounced.cancel = () => {
    if (!timerId) {
      lastArgs = null;
      return false;
    }
    window.clearTimeout(timerId);
    timerId = 0;
    lastArgs = null;
    return true;
  };

  return debounced;
}
