import { useRef } from "react";
import { motion, useScroll, useTransform, useReducedMotion } from "framer-motion";

// Word-by-word scrollytelling statement — each word ignites from ghost to full
// opacity as the reader scrolls through. Spacing uses margin (not text nodes)
// so the tight metrics of Clash Display can never visually collapse words.
export default function ScrollWords({ text, className = "", accentWords = [] }: { text: string; className?: string; accentWords?: string[] }) {
  const ref = useRef<HTMLParagraphElement>(null);
  const reduce = useReducedMotion();
  const { scrollYProgress } = useScroll({ target: ref, offset: ["start 0.85", "end 0.45"] });
  const words = text.split(" ");

  return (
    <p ref={ref} className={className} data-testid="scroll-words">
      {words.map((w, i) => (
        <Word
          key={`${w}-${i}`}
          w={w}
          last={i === words.length - 1}
          accent={accentWords.includes(w.replace(/[.,]/g, ""))}
          progress={scrollYProgress}
          range={[i / words.length, Math.min(1, (i + 1.5) / words.length)]}
          reduce={reduce}
        />
      ))}
    </p>
  );
}

function Word({ w, last, accent, progress, range, reduce }: { w: string; last: boolean; accent: boolean; progress: ReturnType<typeof useScroll>["scrollYProgress"]; range: [number, number]; reduce: boolean | null }) {
  const opacity = useTransform(progress, range, reduce ? [1, 1] : [0.13, 1]);
  const y = useTransform(progress, range, reduce ? [0, 0] : [10, 0]);
  return (
    <motion.span
      className={`inline-block ${accent ? "text-ember" : ""}`}
      style={{ opacity, y, marginRight: last ? 0 : "0.28em" }}
    >
      {w}
    </motion.span>
  );
}
