import { useEffect, useMemo, useRef } from 'react';

/**
 * Returns a debounced wrapper around `fn` that also flushes on unmount AND on
 * page hide (tab close / refresh), so the last edit is never lost — the old app
 * silently dropped unsaved character changes on navigation.
 */
export function useDebouncedCallback<A extends unknown[]>(
  fn: (...args: A) => void,
  delay = 400,
): (...args: A) => void {
  const fnRef = useRef(fn);
  fnRef.current = fn;
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pending = useRef<A | null>(null);

  const flush = () => {
    if (timer.current) {
      clearTimeout(timer.current);
      timer.current = null;
    }
    if (pending.current) {
      fnRef.current(...pending.current);
      pending.current = null;
    }
  };

  useEffect(() => {
    const onHide = () => flush();
    window.addEventListener('pagehide', onHide);
    return () => {
      window.removeEventListener('pagehide', onHide);
      flush(); // flush on unmount
    };
  }, []);

  return useMemo(
    () =>
      (...args: A) => {
        pending.current = args;
        if (timer.current) clearTimeout(timer.current);
        timer.current = setTimeout(() => {
          timer.current = null;
          if (pending.current) {
            fnRef.current(...pending.current);
            pending.current = null;
          }
        }, delay);
      },
    [delay],
  );
}
