"use client";

import { motion } from "framer-motion";
import { Fragment } from "react";
import { useReducedMotionSafe } from "./use-reduced-motion-safe";

type HtmlTag = "h1" | "h2" | "h3" | "p" | "span";

export interface RevealTextProps {
  text: string;
  className?: string;
  as?: HtmlTag;
  /** Split unit — reveal word-by-word (default) or line-by-line. */
  by?: "word" | "line";
  /** Seconds between each word/line's own reveal (default 0.04 — a fast micro-stagger inside this one queue slot). */
  microStagger?: number;
}

/**
 * A single `QueueSection`/`StaggerGrid` slot (it declares the same
 * "hidden"/"visible" variant names as `QueueItem`, so it drops straight
 * into a parent's stagger) that reveals its own text word-by-word or
 * line-by-line once it becomes visible. Each unit is wrapped in an
 * `overflow-hidden` mask so the translateY reveal looks like it's sliding
 * out from behind a clean edge instead of an unclipped word visibly
 * drifting up from nowhere.
 */
export function RevealText({ text, className, as = "p", by = "word", microStagger = 0.04 }: RevealTextProps) {
  const reduced = useReducedMotionSafe();
  const Component = motion[as];
  const units = by === "word" ? text.split(/(\s+)/) : text.split(/\n+/);

  const outerVariants = { hidden: {}, visible: { transition: { staggerChildren: microStagger } } };
  const unitVariants = reduced
    ? { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { duration: 0.4 } } }
    : {
        hidden: { opacity: 0, y: "100%" },
        visible: {
          opacity: 1,
          y: "0%",
          transition: { type: "spring" as const, stiffness: 140, damping: 22, mass: 0.7 },
        },
      };

  return (
    <Component className={className} variants={outerVariants}>
      {units.map((unit, i) =>
        by === "word" && /^\s+$/.test(unit) ? (
          <Fragment key={i}>{unit}</Fragment>
        ) : (
          <span key={i} style={{ display: by === "line" ? "block" : "inline-block", overflow: "hidden" }}>
            <motion.span style={{ display: "inline-block" }} variants={unitVariants}>
              {unit}
            </motion.span>
          </span>
        ),
      )}
    </Component>
  );
}
