/**
 * RippleContainer - Component to render ripple effects
 *
 * Use with the useRipple hook for Material-style button ripples.
 *
 * @example
 * ```tsx
 * import { useRipple, RippleContainer } from '@countermeasure/web-components/react/primitives/ripple'
 *
 * function Button({ children }) {
 *   const { ripples, onPointerDown, onAnimationEnd } = useRipple()
 *   return (
 *     <button onPointerDown={onPointerDown} className="relative overflow-hidden">
 *       {children}
 *       <RippleContainer ripples={ripples} onAnimationEnd={onAnimationEnd} />
 *     </button>
 *   )
 * }
 * ```
 */

import { useState, useCallback, useRef, useEffect, useSyncExternalStore } from 'react'

// --- Inlined useReducedMotion hook ---

const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)'

function getSnapshot(): boolean {
  if (typeof window === 'undefined') return false
  return window.matchMedia(REDUCED_MOTION_QUERY).matches
}

function getServerSnapshot(): boolean {
  return false
}

function subscribe(callback: () => void): () => void {
  const mediaQuery = window.matchMedia(REDUCED_MOTION_QUERY)
  mediaQuery.addEventListener('change', callback)
  return () => mediaQuery.removeEventListener('change', callback)
}

function useReducedMotion(): boolean {
  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
}

// --- Inlined useRipple hook ---

interface Ripple {
  id: number
  x: number
  y: number
  size: number
}

interface UseRippleReturn {
  /** Array of active ripples to render */
  ripples: Ripple[]
  /** Handler to attach to onPointerDown */
  onPointerDown: (event: React.PointerEvent<HTMLElement>) => void
  /** Handler to remove completed ripples */
  onAnimationEnd: (id: number) => void
}

export function useRipple(duration = 600): UseRippleReturn {
  const [ripples, setRipples] = useState<Ripple[]>([])
  const prefersReducedMotion = useReducedMotion()
  const nextId = useRef(0)

  const onPointerDown = useCallback(
    (event: React.PointerEvent<HTMLElement>) => {
      if (prefersReducedMotion) return

      const target = event.currentTarget
      const rect = target.getBoundingClientRect()

      const x = event.clientX - rect.left
      const y = event.clientY - rect.top

      const size = Math.max(rect.width, rect.height) * 2

      const newRipple: Ripple = {
        id: nextId.current++,
        x,
        y,
        size,
      }

      setRipples(prev => [...prev, newRipple])
    },
    [prefersReducedMotion]
  )

  const onAnimationEnd = useCallback((id: number) => {
    setRipples(prev => prev.filter(r => r.id !== id))
  }, [])

  useEffect(() => {
    if (ripples.length === 0) return

    const cleanup = setTimeout(() => {
      setRipples(prev => prev.slice(1))
    }, duration + 100)

    return () => clearTimeout(cleanup)
  }, [ripples.length, duration])

  return { ripples, onPointerDown, onAnimationEnd }
}

// --- RippleContainer component ---

interface RippleContainerProps {
  ripples: Ripple[]
  onAnimationEnd: (id: number) => void
  color?: string
  duration?: number
}

export function RippleContainer({
  ripples,
  onAnimationEnd,
  color = 'rgba(255, 255, 255, 0.3)',
  duration = 600,
}: RippleContainerProps) {
  return (
    <span className="pointer-events-none absolute inset-0 overflow-hidden">
      {ripples.map(ripple => (
        <span
          key={ripple.id}
          className="animate-ripple absolute rounded-full"
          style={{
            left: ripple.x - ripple.size / 2,
            top: ripple.y - ripple.size / 2,
            width: ripple.size,
            height: ripple.size,
            backgroundColor: color,
            animationDuration: `${duration}ms`,
          }}
          onAnimationEnd={() => onAnimationEnd(ripple.id)}
        />
      ))}
    </span>
  )
}
