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

type UseIntersectionObserverOptions = {
  root?: Element | null;
  rootMargin?: string;
  threshold?: number | number[];
  freezeOnceVisible?: boolean;
};

export const useIntersectionObserver = (
  options: UseIntersectionObserverOptions = {},
) => {
  const {
    root = null,
    rootMargin = '200px',
    threshold = 0,
    freezeOnceVisible = true,
  } = options;

  const [hasBeenVisible, setHasBeenVisible] = useState(false);
  const targetRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const element = targetRef.current;

    if (
      !element ||
      !('IntersectionObserver' in window) ||
      (freezeOnceVisible && hasBeenVisible)
    ) {
      return;
    }

    const observer = new IntersectionObserver(
      ([entry]) => {
        const isElementIntersecting = entry.isIntersecting;

        if (isElementIntersecting && !hasBeenVisible) {
          setHasBeenVisible(true);
        }

        if (freezeOnceVisible && isElementIntersecting) {
          observer.unobserve(element);
        }
      },
      {
        root,
        rootMargin,
        threshold,
      },
    );

    observer.observe(element);

    return () => {
      observer.unobserve(element);
    };
  }, [root, rootMargin, threshold, freezeOnceVisible, hasBeenVisible]);

  return {
    targetRef,
    hasBeenVisible,
  };
};
