import { useMemo, useState } from "react";
import useResizeObserver, {
  type ObservedSize,
  type ResizeHandler,
  type ResizeObserverBoxOptions,
  type RoundingFunction,
} from "use-resize-observer";

import { debounce } from "@/helpers/debounce";

interface ResizeObserverOptions<T extends Element> {
  ref?: React.RefObject<T> | T | null;
  onResize?: ResizeHandler;
  box?: ResizeObserverBoxOptions;
  round?: RoundingFunction;
}

interface DebouncedResizeObserverOptions<T extends Element>
  extends ResizeObserverOptions<T> {
  wait?: number;
}

type HookResponse<T extends Element> = {
  ref: React.RefCallback<T>;
} & ObservedSize;

export default function useDebouncedResizeObserver<T extends Element>(
  options: DebouncedResizeObserverOptions<T> = {},
): HookResponse<T> {
  const { wait = 50 } = options;

  const [size, setSize] = useState({ width: 0, height: 0 });

  const onResize = useMemo(
    () =>
      debounce(
        (rect) => {
          setSize({ width: rect.width, height: rect.height });
        },
        wait,
        { leading: true },
      ),
    [wait],
  );
  const { ref } = useResizeObserver({ onResize, ...options });

  return { ref, ...size };
}
