import Autoplay from 'embla-carousel-autoplay';
import useEmblaCarousel from 'embla-carousel-react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { twMerge } from 'tailwind-merge';

export type UseCarouselProps = {
  autoplayDelay?: number;
  loop?: boolean;
  itemLength: number;
};

const useAutoplayCarousel = ({
  autoplayDelay = 5000,
  loop = true,
  itemLength,
}: UseCarouselProps) => {
  const autoplayRef = useRef(
    Autoplay({ delay: autoplayDelay, stopOnInteraction: false })
  );
  const [emblaRef, emblaApi] = useEmblaCarousel({ loop }, [
    autoplayRef.current,
  ]);
  const [selectedIndex, setSelectedIndex] = useState(0);

  const scrollTo = useCallback(
    (index: number) => emblaApi?.scrollTo(index),
    [emblaApi]
  );

  const onSelect = useCallback(() => {
    if (!emblaApi) return;
    setSelectedIndex(emblaApi.selectedScrollSnap());
  }, [emblaApi]);

  useEffect(() => {
    if (!emblaApi) return;

    onSelect();
    emblaApi.on('select', onSelect);

    return () => {
      emblaApi.off('select', onSelect);
    };
  }, [emblaApi, onSelect]);

  const stopAutoplay = useCallback(() => {
    autoplayRef.current.stop();
  }, []);

  const startAutoplay = useCallback(() => {
    autoplayRef.current.play();
  }, []);

  const goToPrevious = useCallback(() => {
    emblaApi?.scrollPrev();
  }, [emblaApi]);
  const goToNext = useCallback(() => {
    emblaApi?.scrollNext();
  }, [emblaApi]);

  const Indicators = useMemo(() => {
    const IndicatorComponent = ({
      className,
      buttonClassName,
    }: {
      className?: string;
      buttonClassName?: string;
    }) => {
      if (itemLength <= 1) return null;

      return (
        <div className={twMerge('flex gap-2', className)}>
          {Array(itemLength)
            .fill(0)
            .map((_, index) => (
              <button
                key={index}
                className={twMerge(
                  'h-1 flex-1 rounded-full transition-all duration-300',
                  index === selectedIndex
                    ? 'bg-foreground-primary'
                    : 'bg-background-tertiary hover:bg-foreground-tertiary',
                  buttonClassName
                )}
                onClick={() => {
                  scrollTo(index);
                }}
                aria-label={`Go to slide ${index + 1}`}
              />
            ))}
        </div>
      );
    };

    IndicatorComponent.displayName = 'CarouselIndicators';
    return IndicatorComponent;
  }, [itemLength, selectedIndex, scrollTo]);

  return useMemo(
    () => ({
      emblaRef,
      selectedIndex,
      scrollTo,
      stopAutoplay,
      startAutoplay,
      Indicators,
      goToPrevious,
      goToNext,
    }),
    [
      emblaRef,
      selectedIndex,
      scrollTo,
      stopAutoplay,
      startAutoplay,
      Indicators,
      goToPrevious,
      goToNext,
    ]
  );
};

export default useAutoplayCarousel;
