"use client"

import * as React from "react"
import { ArrowLeft, ArrowRight } from "lucide-react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

import Autoplay from "embla-carousel-autoplay"
import useEmblaCarousel from "embla-carousel-react"

interface CarouselApi {
  slideNodes(): HTMLElement[]
  on(event: string, listener: (...args: unknown[]) => void): void
  scrollPrev(): void
  scrollNext(): void
  reInit(): void
}

const CarouselContext = React.createContext<CarouselApi | null>(null)

type CarouselProps = React.HTMLAttributes<HTMLDivElement> & {
  opts?: {
    align?: "start" | "center" | "end"
    loop?: boolean
  }
  plugins?: unknown[]
  setApi?: (api: CarouselApi) => void
}

const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
  ({ opts, plugins = [Autoplay()], setApi, className, children, ...props }, ref) => {
    const [api, setApiInternal] = React.useState<CarouselApi | null>(null)

    const [emblaRef, emblaApi] = useEmblaCarousel(opts, plugins)

    React.useEffect(() => {
      setApiInternal(emblaApi ?? null)
    }, [emblaApi])

    React.useEffect(() => {
      if (!api) {
        return
      }

      setApi?.(api)
    }, [api, setApi])

    return (
      <CarouselContext.Provider value={api}>
        <div
          ref={ref}
          className={cn(
            "relative w-full",
            className
          )}
          {...props}
        >
          <div
            className="overflow-hidden"
            ref={emblaRef}
            style={{ touchAction: 'pan-y pinch-zoom' }}
          >
            <div className="flex">{children}</div>
          </div>
        </div>
      </CarouselContext.Provider>
    )
  }
)
Carousel.displayName = "Carousel"

interface CarouselContentProps {
  children: React.ReactNode
  className?: string
}

const CarouselContent = React.forwardRef<HTMLDivElement, CarouselContentProps>(
  ({ children, className }, ref) => (
    <div ref={ref} className={cn("flex", className)}>
      {children}
    </div>
  )
)
CarouselContent.displayName = "CarouselContent"

interface CarouselItemProps {
  children: React.ReactNode
  className?: string
}

const CarouselItem = React.forwardRef<HTMLDivElement, CarouselItemProps>(
  ({ children, className }, ref) => (
    <div
      ref={ref}
      className={cn("min-w-0 shrink-0 grow-0 basis-full pl-4 md:pl-6", className)}
    >
      {children}
    </div>
  )
)
CarouselItem.displayName = "CarouselItem"

const CarouselPrevious = React.forwardRef<
  HTMLButtonElement,
  React.ButtonHTMLAttributes<HTMLButtonElement>
>(({ className, ...props }, ref) => (
  <Button
    ref={ref}
    variant="outline"
    size="icon"
    className={cn(
      "absolute -left-1 top-1/2 -translate-y-1/2 rounded-full h-8 w-8 bg-background/80 backdrop-blur-sm hover:bg-background/90 disabled:pointer-events-none disabled:opacity-50",
      className
    )}
    {...props}
  >
    <ArrowLeft className="h-4 w-4" />
    <span className="sr-only">Previous slide</span>
  </Button>
))
CarouselPrevious.displayName = "CarouselPrevious"

const CarouselNext = React.forwardRef<
  HTMLButtonElement,
  React.ButtonHTMLAttributes<HTMLButtonElement>
>(({ className, ...props }, ref) => (
  <Button
    ref={ref}
    variant="outline"
    size="icon"
    className={cn(
      "absolute -right-1 top-1/2 -translate-y-1/2 rounded-full h-8 w-8 bg-background/80 backdrop-blur-sm hover:bg-background/90 disabled:pointer-events-none disabled:opacity-50",
      className
    )}
    {...props}
  >
    <ArrowRight className="h-4 w-4" />
    <span className="sr-only">Next slide</span>
  </Button>
))
CarouselNext.displayName = "CarouselNext"

export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }
