import { jsx, jsxs } from 'react/jsx-runtime';
import React__default, { useId, useState, useRef, useCallback, useEffect } from 'react';
import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
import { cn } from '../../../utils/cn.js';

/**
 * MorphingText smoothly morphs between different text strings using a blur/fade
 * transition. Two overlapping text layers cross-fade with a Gaussian blur effect
 * to create a seamless morphing appearance.
 *
 * @example
 * ```tsx
 * <MorphingText
 *   texts={["Innovative", "Powerful", "Beautiful"]}
 *   interval={3000}
 *   transitionDuration={800}
 * />
 * ```
 */
const MorphingText = React__default.forwardRef(({ texts, interval = 3000, transitionDuration = 800, loop = true, pauseOnHover = false, currentIndex: controlledIndex, onTextChange, className, ...props }, ref) => {
    const filterId = useId();
    const shouldReduceMotion = useReducedMotion();
    const isControlled = controlledIndex !== undefined;
    const [internalIndex, setInternalIndex] = useState(0);
    const activeIndex = isControlled ? controlledIndex : internalIndex;
    const [isPaused, setIsPaused] = useState(false);
    const intervalRef = useRef(null);
    const hasReachedEnd = useRef(false);
    // Clamp activeIndex to valid range
    const safeIndex = texts.length > 0 ? ((activeIndex % texts.length) + texts.length) % texts.length : 0;
    const advanceIndex = useCallback(() => {
        if (isControlled)
            return;
        setInternalIndex((prev) => {
            const nextIndex = prev + 1;
            if (!loop && nextIndex >= texts.length) {
                hasReachedEnd.current = true;
                return prev;
            }
            const resolvedNext = nextIndex % texts.length;
            onTextChange === null || onTextChange === void 0 ? void 0 : onTextChange(resolvedNext, texts[resolvedNext]);
            return resolvedNext;
        });
    }, [isControlled, loop, texts, onTextChange]);
    // Auto-cycling interval
    useEffect(() => {
        if (isControlled || isPaused || hasReachedEnd.current) {
            return;
        }
        intervalRef.current = setInterval(advanceIndex, interval);
        return () => {
            if (intervalRef.current) {
                clearInterval(intervalRef.current);
                intervalRef.current = null;
            }
        };
    }, [isControlled, isPaused, interval, advanceIndex]);
    // Reset hasReachedEnd when loop changes or texts change
    useEffect(() => {
        hasReachedEnd.current = false;
    }, [loop, texts]);
    // Fire onTextChange for controlled index changes
    useEffect(() => {
        if (isControlled) {
            onTextChange === null || onTextChange === void 0 ? void 0 : onTextChange(safeIndex, texts[safeIndex]);
        }
    }, [isControlled, safeIndex, texts, onTextChange]);
    const handleMouseEnter = () => {
        if (pauseOnHover)
            setIsPaused(true);
    };
    const handleMouseLeave = () => {
        if (pauseOnHover)
            setIsPaused(false);
    };
    if (texts.length === 0) {
        return null;
    }
    const durationSeconds = transitionDuration / 1000;
    const currentText = texts[safeIndex];
    // Reduced motion: instant swap with no animation
    if (shouldReduceMotion) {
        return (jsx("div", { ref: ref, className: cn('relative inline-block', className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, "aria-live": "polite", "aria-atomic": "true", ...props, children: jsx("span", { children: currentText }) }));
    }
    return (jsxs("div", { ref: ref, className: cn('relative inline-block', className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, "aria-live": "polite", "aria-atomic": "true", ...props, children: [jsx("svg", { className: "absolute h-0 w-0", "aria-hidden": "true", children: jsx("defs", { children: jsx("filter", { id: `${filterId}-blur`, children: jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "0" }) }) }) }), jsx("span", { className: "invisible block", "aria-hidden": "true", children: currentText }), jsx(AnimatePresence, { mode: "popLayout", initial: false, children: jsx(motion.span, { className: "absolute inset-0 flex items-center", initial: { opacity: 0, filter: 'blur(8px)' }, animate: { opacity: 1, filter: 'blur(0px)' }, exit: { opacity: 0, filter: 'blur(8px)' }, transition: {
                        duration: durationSeconds,
                        ease: 'easeInOut',
                    }, children: currentText }, safeIndex) })] }));
});
MorphingText.displayName = "MorphingText";

export { MorphingText };
