// ScrollReveal — wrap a section to fade + slide it up when it
// enters the viewport. One-shot (never animates back out). Uses
// IntersectionObserver, no scroll listeners, no main-thread work.
//
// `prefers-reduced-motion: reduce` short-circuits to instantly visible.

import { useEffect, useRef, useState, type ReactNode } from 'react'
import { cn } from '../cn'

interface ScrollRevealProps {
  readonly children: ReactNode
  readonly className?: string
  /** Pixel distance the element rises from. Default 24. */
  readonly distance?: number
  /** Delay before the animation runs, in ms. Default 0. */
  readonly delay?: number
  /** Intersection threshold 0…1. Default 0.15 — element starts
   *  animating when 15% of it is in view. */
  readonly threshold?: number
  /** Disable the animation entirely (passthrough). Useful when the
   *  parent is already a stagger container. */
  readonly disabled?: boolean
}

export const ScrollReveal = ({
  children, className, distance = 24, delay = 0,
  threshold = 0.15, disabled = false,
}: ScrollRevealProps): ReactNode => {
  const ref = useRef<HTMLDivElement>(null)
  const [shown, setShown] = useState(disabled)

  useEffect(() => {
    if (disabled) return
    if (typeof IntersectionObserver === 'undefined') {
      // Old browser — just show instantly.
      setShown(true)
      return
    }
    const node = ref.current
    if (!node) return
    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            setShown(true)
            observer.disconnect()
            return
          }
        }
      },
      { threshold, rootMargin: '0px 0px -10% 0px' },
    )
    observer.observe(node)
    return () => observer.disconnect()
  }, [threshold, disabled])

  return (
    <div
      ref={ref}
      className={cn('motion-safe:transition-all motion-safe:duration-700 motion-safe:ease-out', className)}
      style={
        shown
          ? { opacity: 1, transform: 'translate3d(0, 0, 0)', transitionDelay: `${delay}ms` }
          : { opacity: 0, transform: `translate3d(0, ${distance}px, 0)` }
      }
    >
      {children}
    </div>
  )
}
