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

/**
 * Custom hook to detect if the user has scrolled to the end of a scrollable element.
 *
 * @param {Object} opts - The options object.
 * @param {React.Ref} [opts.ref] - A React ref to the scrollable element. If not provided, the hook creates a default ref.
 * @param {number} [opts.buffer=0] - A buffer distance (in pixels) to adjust the point at which the hook considers the user to be "at the end" of the scrollable content.
 * @param {'vertical'|'horizontal'} [opts.direction='vertical'] - The scroll direction to observe ('vertical' or 'horizontal'). Default is 'vertical'.
 *
 * @returns {[React.Ref, boolean]} - A tuple where the first item is the ref to attach to the scrollable element and the second item is a boolean indicating if the user has scrolled to the end (considering the buffer).
 */
function useAtScrollEnd(opts = {}) {
  const defaultRef = useRef();
  const {
    ref = defaultRef,
    buffer = 0,
    direction = 'vertical'
  } = opts;
  const [isAtEnd, setIsAtEnd] = useState(false);
  useEffect(() => {
    const handleScroll = () => {
      if (ref.current) {
        let scrollPos;
        let scrollSize;
        let clientSize;
        if (direction === 'horizontal') {
          scrollPos = ref.current.scrollLeft;
          scrollSize = ref.current.scrollWidth;
          clientSize = ref.current.clientWidth;
        } else {
          scrollPos = ref.current.scrollTop;
          scrollSize = ref.current.scrollHeight;
          clientSize = ref.current.clientHeight;
        }

        // Check if we're near the end (using the buffer)
        if (scrollPos + clientSize + buffer >= scrollSize) {
          setIsAtEnd(true);
        } else {
          setIsAtEnd(false);
        }
      }
    };
    if (ref.current) {
      ref.current.addEventListener('scroll', handleScroll);
    }

    // Cleanup the event listener
    return () => {
      if (ref.current) {
        ref.current.removeEventListener('scroll', handleScroll);
      }
    };
  }, [ref, buffer, direction]);
  return [ref, isAtEnd];
}
export default useAtScrollEnd;