"use client";

import { useCallback, useEffect, useRef, useState, type ReactNode } from "react";
import useEmblaCarousel from "embla-carousel-react";
import Autoplay from "embla-carousel-autoplay";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";

export interface CarouselProps {
  children: ReactNode[];
  slideClassName?: string;
  autoplay?: boolean;
  autoplayDelayMs?: number;
  showDots?: boolean;
  showArrows?: boolean;
  ariaLabel: string;
  className?: string;
}

export function Carousel({
  children,
  slideClassName = "basis-full sm:basis-1/2 lg:basis-1/3",
  autoplay = false,
  autoplayDelayMs = 5000,
  showDots = true,
  showArrows = true,
  ariaLabel,
  className,
}: CarouselProps) {
  const autoplayPlugin = useRef(
    Autoplay({
      delay: autoplayDelayMs,
      stopOnInteraction: false,
      stopOnMouseEnter: true,
      playOnInit: true,
    }),
  );

  const [emblaRef, emblaApi] = useEmblaCarousel(
    { loop: true, align: "start" },
    autoplay ? [autoplayPlugin.current] : [],
  );

  useEffect(() => {
    if (!emblaApi || !autoplay) return;
    const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const autoplayApi = emblaApi.plugins().autoplay;
    if (reducedMotion) {
      autoplayApi?.stop();
    } else {
      autoplayApi?.play();
    }
  }, [emblaApi, autoplay]);

  const [selectedIndex, setSelectedIndex] = useState(0);
  const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);

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

  useEffect(() => {
    if (!emblaApi) return;
    setScrollSnaps(emblaApi.scrollSnapList());
    onSelect();
    emblaApi.on("select", onSelect);
    emblaApi.on("reInit", onSelect);
    return () => {
      emblaApi.off("select", onSelect);
      emblaApi.off("reInit", onSelect);
    };
  }, [emblaApi, onSelect]);

  return (
    <div className={cn("relative", className)} aria-label={ariaLabel} role="region">
      <div className="overflow-hidden" ref={emblaRef}>
        <div className="-ml-4 flex sm:-ml-5">
          {children.map((child, i) => (
            <div key={i} className={cn("min-w-0 shrink-0 grow-0 pl-4 sm:pl-5", slideClassName)}>
              {child}
            </div>
          ))}
        </div>
      </div>

      {showArrows && (
        <>
          <button
            type="button"
            aria-label="Previous slide"
            onClick={() => emblaApi?.scrollPrev()}
            className="absolute left-2 top-1/2 hidden h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full border border-neutral-200 bg-white shadow-md hover:bg-neutral-50 md:flex"
          >
            <ChevronLeft className="h-5 w-5 text-neutral-700" aria-hidden />
          </button>
          <button
            type="button"
            aria-label="Next slide"
            onClick={() => emblaApi?.scrollNext()}
            className="absolute right-2 top-1/2 hidden h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full border border-neutral-200 bg-white shadow-md hover:bg-neutral-50 md:flex"
          >
            <ChevronRight className="h-5 w-5 text-neutral-700" aria-hidden />
          </button>
        </>
      )}

      {showDots && scrollSnaps.length > 1 && (
        <div className="mt-5 flex justify-center gap-2">
          {scrollSnaps.map((_, i) => (
            <button
              key={i}
              type="button"
              aria-label={`Go to slide ${i + 1}`}
              aria-current={i === selectedIndex}
              onClick={() => emblaApi?.scrollTo(i)}
              className={cn(
                "h-2 rounded-full transition-all duration-300 hover:bg-primary-400",
                i === selectedIndex ? "w-7 bg-primary-700" : "w-2 bg-neutral-300",
              )}
            />
          ))}
        </div>
      )}
    </div>
  );
}
