"use client"

import { useRef, useCallback, useEffect } from "react"
import Image from "next/image"
import type { WeddingGalleryData } from "@/lib/strapi/types"

function GalleryImage({ src, scale = 1 }: { src?: string; scale?: number }) {
  if (!src) return null

  return (
    <span className="block relative w-full h-full">
      <Image
        src={src}
        alt="Wedding venue"
        fill
        sizes={scale < 1 ? "55vw" : "45vw"}
        loading="lazy"
        className="object-cover"
        draggable={false}
      />
    </span>
  )
}

function GalleryCard({ scale = 1, images }: { scale?: number; images: string[] }) {
  const s = (v: number) => v * scale
  return (
    <div className="flex gap-[16px] shrink-0" style={{ height: s(665), gap: s(16) }}>
      <div className="flex flex-col shrink-0" style={{ width: s(575), gap: s(16) }}>
        <div className="overflow-hidden rounded-lg" style={{ height: s(181) }}>
          <GalleryImage src={images[0]} scale={scale} />
        </div>
        <div className="flex" style={{ gap: s(12) }}>
          <div className="flex flex-col flex-1" style={{ gap: s(16) }}>
            <div className="flex" style={{ gap: s(12) }}>
              <div className="flex-1 overflow-hidden rounded-lg" style={{ height: s(156) }}>
                <GalleryImage src={images[1]} scale={scale} />
              </div>
              <div className="flex-1 overflow-hidden rounded-lg" style={{ height: s(156) }}>
                <GalleryImage src={images[2]} scale={scale} />
              </div>
            </div>
            <div className="overflow-hidden rounded-lg" style={{ height: s(296) }}>
              <GalleryImage src={images[3]} scale={scale} />
            </div>
          </div>
        </div>
      </div>

      <div className="flex flex-col shrink-0" style={{ width: s(890), gap: s(16) }}>
        <div className="flex" style={{ gap: s(16) }}>
          <div className="overflow-hidden rounded-lg shrink-0" style={{ width: s(386), height: s(432) }}>
            <GalleryImage src={images[4]} scale={scale} />
          </div>
          <div className="flex flex-col shrink-0" style={{ width: s(488), gap: s(16) }}>
            <div className="overflow-hidden rounded-lg" style={{ height: s(208) }}>
              <GalleryImage src={images[5]} scale={scale} />
            </div>
            <div className="overflow-hidden rounded-lg" style={{ height: s(208) }}>
              <GalleryImage src={images[6]} scale={scale} />
            </div>
          </div>
        </div>
        <div className="overflow-hidden rounded-lg" style={{ height: s(217) }}>
          <GalleryImage src={images[7]} scale={scale} />
        </div>
      </div>
    </div>
  )
}

function useInfiniteDragScroll() {
  const scrollRef = useRef<HTMLDivElement>(null)
  const isDragging = useRef(false)
  const isVisible = useRef(false)
  const startX = useRef(0)
  const scrollLeftStart = useRef(0)
  const animationRef = useRef<number>(0)

  const resetToMiddle = useCallback(() => {
    const el = scrollRef.current
    if (!el) return
    const maxScroll = el.scrollWidth - el.clientWidth
    el.scrollLeft = maxScroll / 2
  }, [])

  const handleScroll = useCallback(() => {
    const el = scrollRef.current
    if (!el) return
    const thirdWidth = el.scrollWidth / 3
    if (el.scrollLeft < thirdWidth * 0.1) {
      el.scrollLeft += thirdWidth
    } else if (el.scrollLeft > thirdWidth * 2.5) {
      el.scrollLeft -= thirdWidth
    }
  }, [])

  const handleMouseDown = useCallback((e: React.MouseEvent) => {
    const el = scrollRef.current
    if (!el) return
    isDragging.current = true
    startX.current = e.pageX
    scrollLeftStart.current = el.scrollLeft
    el.style.cursor = "grabbing"
    el.style.userSelect = "none"
  }, [])

  const handleMouseMove = useCallback((e: React.MouseEvent) => {
    if (!isDragging.current || !scrollRef.current) return
    e.preventDefault()
    const walk = (e.pageX - startX.current) * 1.5
    scrollRef.current.scrollLeft = scrollLeftStart.current - walk
  }, [])

  const handleMouseUp = useCallback(() => {
    isDragging.current = false
    if (scrollRef.current) {
      scrollRef.current.style.cursor = "grab"
      scrollRef.current.style.userSelect = ""
    }
  }, [])

  const touchStartX = useRef(0)
  const touchScrollLeft = useRef(0)

  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    const el = scrollRef.current
    if (!el) return
    touchStartX.current = e.touches[0].pageX
    touchScrollLeft.current = el.scrollLeft
  }, [])

  const handleTouchMove = useCallback((e: React.TouchEvent) => {
    if (!scrollRef.current) return
    const walk = (e.touches[0].pageX - touchStartX.current) * 1.5
    scrollRef.current.scrollLeft = touchScrollLeft.current - walk
  }, [])

  const startAutoScroll = useCallback(() => {
    const el = scrollRef.current
    if (!el) return
    const speed = 0.5
    const animate = () => {
      if (isVisible.current && !isDragging.current && el) {
        el.scrollLeft += speed
      }
      animationRef.current = requestAnimationFrame(animate)
    }
    animationRef.current = requestAnimationFrame(animate)
  }, [])

  useEffect(() => {
    const el = scrollRef.current
    resetToMiddle()
    startAutoScroll()

    const observer = el && "IntersectionObserver" in window
      ? new IntersectionObserver(([entry]) => {
          isVisible.current = entry.isIntersecting
        }, { rootMargin: "200px" })
      : null

    if (el && observer) observer.observe(el)
    if (!observer) isVisible.current = true

    const handleGlobalMouseUp = () => {
      isDragging.current = false
      if (scrollRef.current) {
        scrollRef.current.style.cursor = "grab"
        scrollRef.current.style.userSelect = ""
      }
    }
    window.addEventListener("mouseup", handleGlobalMouseUp)

    return () => {
      observer?.disconnect()
      window.removeEventListener("mouseup", handleGlobalMouseUp)
      cancelAnimationFrame(animationRef.current)
    }
  }, [resetToMiddle, startAutoScroll])

  return {
    scrollRef,
    handlers: {
      onScroll: handleScroll,
      onMouseDown: handleMouseDown,
      onMouseMove: handleMouseMove,
      onMouseUp: handleMouseUp,
      onMouseLeave: handleMouseUp,
      onTouchStart: handleTouchStart,
      onTouchMove: handleTouchMove,
    },
  }
}

export default function WeddingGallery({ data }: { data: WeddingGalleryData }) {
  const { scrollRef, handlers } = useInfiniteDragScroll()

  const cards: string[][] = []
  if (data.images.length >= 8) cards.push(data.images.slice(0, 8))
  if (data.images.length >= 16) cards.push(data.images.slice(8, 16))

  const renderSets = cards.length >= 2
    ? [cards[0], cards[1], cards[0]]
    : cards.length === 1
      ? [cards[0], cards[0], cards[0]]
      : []

  if (renderSets.length === 0) return null

  return (
    <section className="gallery-perf-section relative w-full bg-white py-[46px] md:py-[46px] overflow-hidden">
      <div className="px-[18px] md:px-0 md:w-[1296px] md:mx-auto flex flex-col md:flex-row md:items-start md:justify-between gap-[20px] md:gap-0 mb-[32px] md:mb-[46px]">
        <div className="bg-[#ebebeb] inline-flex gap-[8px] items-center px-[24px] py-[12px] rounded-full self-start">
          <img src={data.badgeIcon} alt="" loading="lazy" decoding="async" className="w-[17px] h-4" />
          <span className="font-heading text-black text-[16px] leading-[1.2] uppercase">
            <span className="hidden md:inline">{data.badgeDesktopText}</span>
            <span className="md:hidden">{data.badgeMobileText}</span>
          </span>
        </div>
        <div className="flex flex-col gap-[16px] md:w-[461px]">
          <p className="text-[16px] leading-[1.5] font-medium text-[rgba(42,48,54,0.6)]">
            {data.description}
          </p>
          <div className="w-full h-px bg-[#d9d9d9]" />
        </div>
      </div>

      <div
        ref={scrollRef}
        {...handlers}
        className="overflow-x-hidden cursor-grab select-none"
        style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
      >
        <div className="gallery-motion-track flex gap-[16px] md:gap-[16px] w-max">
          {renderSets.map((set, i) => (
            <div key={`d-${i}`} className="hidden md:flex">
              <GalleryCard images={set} />
            </div>
          ))}
          {renderSets.map((set, i) => (
            <div key={`m-${i}`} className="md:hidden flex">
              <GalleryCard scale={0.55} images={set} />
            </div>
          ))}
        </div>
      </div>
    </section>
  )
}
