"use client";

import { useEffect, useRef, useState } from "react";
import { useReducedMotion } from "framer-motion";

interface TypewriterTextProps {
  text: string;
  speed?: number;
  delay?: number;
  className?: string;
}

export default function TypewriterText({ text, speed = 24, delay = 120, className = "" }: TypewriterTextProps) {
  const rootRef = useRef<HTMLSpanElement>(null);
  const [visibleText, setVisibleText] = useState("");
  const [typing, setTyping] = useState(false);
  const reducedMotion = useReducedMotion();

  useEffect(() => {
    const root = rootRef.current;
    if (!root) return;

    if (reducedMotion) return;

    let timeoutId: number | undefined;
    let intervalId: number | undefined;
    let started = false;

    const start = () => {
      if (started) return;
      started = true;
      setVisibleText("");
      setTyping(true);
      timeoutId = window.setTimeout(() => {
        let index = 0;
        intervalId = window.setInterval(() => {
          index += 1;
          setVisibleText(text.slice(0, index));
          if (index >= text.length) {
            window.clearInterval(intervalId);
            setTyping(false);
          }
        }, speed);
      }, delay);
    };

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (!entry.isIntersecting) return;
        observer.disconnect();
        start();
      },
      { threshold: 0.35, rootMargin: "0px 0px -8%" },
    );

    observer.observe(root);
    return () => {
      observer.disconnect();
      if (timeoutId !== undefined) window.clearTimeout(timeoutId);
      if (intervalId !== undefined) window.clearInterval(intervalId);
    };
  }, [delay, reducedMotion, speed, text]);

  const renderedText = reducedMotion ? text : visibleText;

  return (
    <span ref={rootRef} className={`relative block ${className}`} aria-label={text}>
      <span aria-hidden="true" className="invisible block">{text}</span>
      <span aria-hidden="true" className="absolute inset-0 block">
        {renderedText}
        <span
          className={`ml-[.06em] inline-block h-[.78em] w-[2px] translate-y-[.05em] bg-current transition-opacity ${typing ? "animate-pulse opacity-65" : "opacity-0"}`}
        />
      </span>
    </span>
  );
}
