import { motion, useReducedMotion } from "framer-motion";
import type { RevealProps } from "../types";

export default function Reveal({ children, delay = 0, y = 36, className = "", as: Tag = "div" }: RevealProps) {
  const reduce = useReducedMotion();
  if (reduce) return <Tag className={className}>{children}</Tag>;
  return (
    <motion.div
      className={className}
      initial={{ opacity: 0, y }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, amount: 0.15 }}
      transition={{ duration: 0.8, delay, ease: [0.22, 1, 0.36, 1] }}
    >
      {children}
    </motion.div>
  );
}

// Masked line-by-line kinetic reveal for headlines.
// The observer sits on the unclipped mask span; the inner line animates via variant propagation,
// otherwise a fully-clipped child can never satisfy an IntersectionObserver threshold.
interface KineticLinesProps {
  lines: string[];
  className?: string;
  lineClass?: string[];
  delay?: number;
}

export function KineticLines({ lines, className = "", lineClass = [], delay = 0 }: KineticLinesProps) {
  const reduce = useReducedMotion();
  const container = {
    hidden: {},
    visible: { transition: { staggerChildren: 0.12, delayChildren: delay } },
  };
  const line = {
    hidden: reduce ? { opacity: 1 } : { y: "110%" },
    visible: { y: "0%", transition: { duration: 1.1, ease: [0.85, 0, 0.15, 1] as const } },
  };
  return (
    <motion.span
      className={`block ${className}`}
      variants={container}
      initial="hidden"
      whileInView="visible"
      viewport={{ once: true, amount: 0.2 }}
    >
      {lines.map((l, i) => (
        <span key={i} className="block overflow-hidden pb-[0.08em] -mb-[0.08em]">
          <motion.span className={`block will-change-transform ${lineClass?.[i] || ""}`} variants={line}>
            {l}
          </motion.span>
        </span>
      ))}
    </motion.span>
  );
}
