"use client";

/**
 * KineticText — word/line masked reveal driven by ScrollTrigger.
 *
 * Splits the given text into words wrapped in overflow-hidden masks (manual
 * spans — no premium SplitText plugin) and slides each word up from below as it
 * enters the viewport, with a stagger. Renders the text as real, selectable DOM
 * so it stays accessible and SEO-safe; animation only transforms (perf-friendly).
 *
 * With reduced-motion, the text simply appears (no transform).
 */

import { createElement, useEffect, useRef, type ElementType } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

type Props = {
  text: string;
  as?: ElementType;
  className?: string;
  /** Delay the whole reveal (s). */
  delay?: number;
  /** Start animation on mount instead of on scroll (for the hero). */
  immediate?: boolean;
  /** Mark a word index range as gradient-highlighted. */
  highlight?: [number, number];
};

export default function KineticText({
  text,
  as: Tag = "span",
  className = "",
  delay = 0,
  immediate = false,
  highlight,
}: Props) {
  const ref = useRef<HTMLElement>(null);
  const words = text.split(" ");

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const inner = gsap.utils.toArray<HTMLElement>(".ktext__in", el);

    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      gsap.set(inner, { yPercent: 0, opacity: 1 });
      return;
    }

    const ctx = gsap.context(() => {
      gsap.set(inner, { yPercent: 118 });
      const anim: gsap.TweenVars = {
        yPercent: 0,
        duration: 1.0,
        ease: "power4.out",
        stagger: 0.045,
        delay,
      };
      if (!immediate) {
        anim.scrollTrigger = { trigger: el, start: "top 88%" };
      }
      gsap.to(inner, anim);
    }, el);

    return () => ctx.revert();
  }, [delay, immediate]);

  const children = words.map((w, i) => {
    const hot =
      highlight && i >= highlight[0] && i <= highlight[1] ? " ktext__word--grad" : "";
    return (
      <span className={`ktext__word${hot}`} key={i}>
        <span className="ktext__in">{w}</span>
        {i < words.length - 1 ? " " : ""}
      </span>
    );
  });

  return createElement(Tag, { ref, className: `ktext ${className}` }, children);
}
