"use client"

import {
  useLayoutEffect,
  useRef,
  useState,
  type ReactNode,
} from "react"
import { cn } from "@/lib/utils"

interface LandingRevealProps {
  children: ReactNode
  className?: string
  /** Délai (s) appliqué à la transition — pour le stagger. */
  delay?: number
  as?: "div" | "section" | "li" | "span"
}

function isInRevealViewport(node: HTMLElement, margin = 36): boolean {
  const rect = node.getBoundingClientRect()
  return rect.top < window.innerHeight - margin && rect.bottom > margin
}

/** Révèle son contenu à l'entrée dans le viewport (une seule fois). */
export function LandingReveal({
  children,
  className,
  delay = 0,
  as: Tag = "div",
}: LandingRevealProps) {
  const ref = useRef<HTMLElement | null>(null)
  const [mounted, setMounted] = useState(false)
  const [revealed, setRevealed] = useState(true)

  useLayoutEffect(() => {
    setMounted(true)
    const node = ref.current
    if (!node) return

    if (typeof IntersectionObserver === "undefined") {
      setRevealed(true)
      return
    }

    if (isInRevealViewport(node)) {
      setRevealed(true)
      return
    }

    setRevealed(false)
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries.some((entry) => entry.isIntersecting)) {
          setRevealed(true)
          observer.disconnect()
        }
      },
      { threshold: 0.12, rootMargin: "0px 0px -36px 0px" }
    )
    observer.observe(node)
    return () => observer.disconnect()
  }, [])

  return (
    <Tag
      ref={ref as never}
      className={cn("landing-reveal", className)}
      data-revealed={
        mounted ? (revealed ? "true" : "false") : undefined
      }
      suppressHydrationWarning
      style={delay ? ({ "--reveal-delay": `${delay}s` } as React.CSSProperties) : undefined}
    >
      {children}
    </Tag>
  )
}
