import { useRef, type ReactNode } from "react";
import { motion, useInView, useReducedMotion } from "motion/react";

/**
 * Reveals its children as if a paint roller swept across the line:
 * a red roller mark travels left-to-right, and the text is uncovered
 * in the wet paint it leaves behind. The trailing edge is deliberately
 * uneven so it reads as hand-rolled rather than a clean CSS wipe.
 */
export default function RollerReveal({
  children,
  className = "",
  delay = 0,
  as: Tag = "span",
}: {
  children: ReactNode;
  className?: string;
  delay?: number;
  as?: "span" | "div";
}) {
  const ref = useRef<HTMLDivElement>(null);
  const reduce = useReducedMotion();
  const inView = useInView(ref, { once: true, margin: "0px 0px -12% 0px" });
  const play = reduce ? true : inView;
  const duration = 1.1;

  return (
    <Tag ref={ref as never} className={`relative block overflow-hidden ${className}`}>
      <motion.span
        className="block"
        variants={{
          off: { clipPath: "inset(0 100% 0 0)" },
          on: { clipPath: "inset(0 0% 0 0)" },
        }}
        initial={reduce ? "on" : "off"}
        animate={play ? "on" : "off"}
        transition={{ duration, delay, ease: [0.65, 0, 0.35, 1] }}
      >
        {children}
      </motion.span>

      {/* the roller head + wet paint edge */}
      <motion.span
        aria-hidden="true"
        className="pointer-events-none absolute inset-y-0 left-0 w-[6%] min-w-[26px]"
        variants={{
          off: { x: "-120%", opacity: 0 },
          on: { x: ["-120%", "740%"], opacity: [0, 1, 1, 0] },
        }}
        initial="off"
        animate={reduce ? "off" : play ? "on" : "off"}
        transition={{
          duration,
          delay,
          ease: [0.65, 0, 0.35, 1],
          times: [0, 0.08, 0.82, 1],
        }}
      >
        <span className="absolute inset-y-[8%] right-0 left-0 rounded-[3px] bg-[var(--brand)] opacity-90" />
        <span className="absolute inset-y-[8%] -right-2 w-3 bg-[var(--brand)] opacity-60 blur-[3px]" />
      </motion.span>
    </Tag>
  );
}
