import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
import { ChevronLeft, ChevronRight } from 'lucide-react'
import './TestimonialSlider.css'

const LOOP_SETS = 9
const MIDDLE_SET = Math.floor(LOOP_SETS / 2)

/**
 * Manual testimonial slider (carousel).
 * Equal heights, horizontal scroll, no autoplay.
 */
export default function TestimonialSlider({ testimonials = [] }) {
  const scrollerRef = useRef(null)
  const dragStateRef = useRef({ isDragging: false, startX: 0, scrollLeft: 0 })
  const recenterTimerRef = useRef(null)
  const [isDragging, setIsDragging] = useState(false)
  const [activeIndex, setActiveIndex] = useState(0)
  const canLoop = testimonials.length > 1
  const visibleTestimonials = canLoop
    ? Array.from({ length: LOOP_SETS }, () => testimonials).flat()
    : testimonials

  const getCenteredScrollLeft = (cardIndex) => {
    const scroller = scrollerRef.current
    const card = scroller?.querySelectorAll('.testimonial-card')[cardIndex]
    if (!scroller || !card) return 0

    return card.offsetLeft - (scroller.clientWidth - card.offsetWidth) / 2
  }

  const getClosestCardIndex = () => {
    const scroller = scrollerRef.current
    const cards = Array.from(scroller?.querySelectorAll('.testimonial-card') || [])
    if (!scroller || cards.length === 0) return 0

    const scrollerCenter = scroller.scrollLeft + scroller.clientWidth / 2
    return cards.reduce((closestIndex, card, index) => {
      const cardCenter = card.offsetLeft + card.offsetWidth / 2
      const closestCard = cards[closestIndex]
      const closestCenter = closestCard.offsetLeft + closestCard.offsetWidth / 2

      return Math.abs(cardCenter - scrollerCenter) < Math.abs(closestCenter - scrollerCenter)
        ? index
        : closestIndex
    }, 0)
  }

  const centerCard = (cardIndex, behavior = 'auto') => {
    const scroller = scrollerRef.current
    if (!scroller) return
    const normalizedIndex = ((cardIndex % testimonials.length) + testimonials.length) % testimonials.length
    setActiveIndex(normalizedIndex)

    scroller.scrollTo({
      left: getCenteredScrollLeft(cardIndex),
      behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : behavior,
    })
  }

  useLayoutEffect(() => {
    if (!canLoop) return undefined

    const frameId = window.requestAnimationFrame(() => {
      const scroller = scrollerRef.current
      const card = scroller?.querySelectorAll('.testimonial-card')[testimonials.length * MIDDLE_SET]
      if (!scroller || !card) return

      scroller.scrollLeft = card.offsetLeft - (scroller.clientWidth - card.offsetWidth) / 2
    })

    return () => window.cancelAnimationFrame(frameId)
  }, [canLoop, testimonials.length])

  useEffect(() => () => window.clearTimeout(recenterTimerRef.current), [])

  const scrollByCard = (direction) => {
    const scroller = scrollerRef.current
    if (!scroller) return

    const targetIndex = getClosestCardIndex() + direction
    centerCard(targetIndex, 'smooth')

    window.clearTimeout(recenterTimerRef.current)
    recenterTimerRef.current = window.setTimeout(recenterIfNeeded, 450)
  }

  const recenterIfNeeded = () => {
    const scroller = scrollerRef.current
    if (!canLoop || !scroller) return

    const currentIndex = getClosestCardIndex()
    const normalizedIndex = ((currentIndex % testimonials.length) + testimonials.length) % testimonials.length
    setActiveIndex(normalizedIndex)
    const lowBoundary = testimonials.length
    const highBoundary = testimonials.length * (LOOP_SETS - 1)
    if (currentIndex >= lowBoundary && currentIndex < highBoundary) return

    centerCard(testimonials.length * MIDDLE_SET + normalizedIndex)
  }

  const handlePointerDown = (event) => {
    if (event.pointerType === 'touch') return
    const scroller = scrollerRef.current
    if (!scroller) return

    dragStateRef.current = {
      isDragging: true,
      startX: event.clientX,
      scrollLeft: scroller.scrollLeft,
    }
    setIsDragging(true)
    scroller.setPointerCapture(event.pointerId)
  }

  const handlePointerMove = (event) => {
    const scroller = scrollerRef.current
    const dragState = dragStateRef.current
    if (!scroller || !dragState.isDragging) return

    scroller.scrollLeft = dragState.scrollLeft - (event.clientX - dragState.startX)
  }

  const stopDragging = (event) => {
    const scroller = scrollerRef.current
    dragStateRef.current.isDragging = false
    setIsDragging(false)
    recenterIfNeeded()

    if (scroller?.hasPointerCapture?.(event.pointerId)) {
      scroller.releasePointerCapture(event.pointerId)
    }
  }

  const handleKeyDown = (event) => {
    if (event.key === 'ArrowLeft') {
      event.preventDefault()
      scrollByCard(-1)
    } else if (event.key === 'ArrowRight') {
      event.preventDefault()
      scrollByCard(1)
    }
  }

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

  return (
    <section className="testimonials-section app-container" aria-labelledby="testimonials-heading">
      <h2 id="testimonials-heading" className="sr-only">Testimonials</h2>
      <div className="testimonial-slider-controls" aria-label="Testimonials wechseln">
        <button type="button" className="testimonial-nav-button" onClick={() => scrollByCard(-1)} aria-label="Vorheriges Testimonial">
          <ChevronLeft size={22} aria-hidden="true" />
        </button>
        <button type="button" className="testimonial-nav-button" onClick={() => scrollByCard(1)} aria-label="Nächstes Testimonial">
          <ChevronRight size={22} aria-hidden="true" />
        </button>
      </div>
      <p className="sr-only" role="status" aria-live="polite">
        Testimonial {activeIndex + 1} von {testimonials.length}
      </p>
      <div
        className={`testimonial-scroll-container${isDragging ? ' dragging' : ''}`}
        ref={scrollerRef}
        role="region"
        aria-label={`Testimonial ${testimonials.length > 1 ? 'Karussell' : ''}`}
        aria-roledescription="Karussell"
        tabIndex="0"
        onKeyDown={handleKeyDown}
        onPointerDown={handlePointerDown}
        onPointerMove={handlePointerMove}
        onPointerUp={stopDragging}
        onPointerCancel={stopDragging}
        onPointerLeave={(event) => {
          if (dragStateRef.current.isDragging) stopDragging(event)
        }}
      >
        {visibleTestimonials.map((current, i) => (
          <div className="testimonial-card glass-panel" key={`${current.name}-${i}`} aria-hidden={canLoop && Math.floor(i / testimonials.length) !== MIDDLE_SET}>
            <div className="testimonial-quote">
              <span className="quote-mark">"</span>
              <p>{current.quote}</p>
            </div>
            <div className="testimonial-author">
              {current.photo && <img src={current.photo} alt={current.name} className="author-photo" loading="lazy" />}
              <div>
                <strong>{current.name}</strong>
                <span>{current.role}</span>
              </div>
            </div>
          </div>
        ))}
      </div>
    </section>
  )
}
