import { useRef, useCallback, useEffect } from 'react';
import { useReducedMotion, useMotionValue, useSpring } from 'motion/react';

function useIdleAnimation({ enabled = true, swayAmount = 2, swaySpeed = 1, breathAmount = 0.01, headTiltAmount = 3, headNudgeAmount = 1.5, phaseOffset = 0, } = {}) {
    const shouldReduceMotion = useReducedMotion();
    const rafRef = useRef(0);
    const startTimeRef = useRef(null);
    const isFirstFrame = useRef(true);
    const rawSway = useMotionValue(0);
    const rawBob = useMotionValue(0);
    const rawBreath = useMotionValue(1);
    const rawHeadTilt = useMotionValue(0);
    const rawHeadX = useMotionValue(0);
    const rawHeadY = useMotionValue(0);
    const sway = useSpring(rawSway, { stiffness: 40, damping: 15 });
    const bob = useSpring(rawBob, { stiffness: 40, damping: 15 });
    const breath = useSpring(rawBreath, { stiffness: 40, damping: 15 });
    const headTilt = useSpring(rawHeadTilt, { stiffness: 30, damping: 12 });
    const headX = useSpring(rawHeadX, { stiffness: 35, damping: 14 });
    const headY = useSpring(rawHeadY, { stiffness: 35, damping: 14 });
    const animate = useCallback((time) => {
        if (startTimeRef.current === null)
            startTimeRef.current = time;
        const t = (time - startTimeRef.current) / 1000 + phaseOffset;
        // Body sway: slow sinusoidal
        const swayVal = Math.sin(t * 0.8 * swaySpeed) * swayAmount;
        rawSway.set(swayVal);
        // Body bob: slightly different frequency
        const bobVal = Math.sin(t * 1.2 * swaySpeed) * (swayAmount * 0.5);
        rawBob.set(bobVal);
        // Breathing: subtle scale oscillation
        const breathVal = 1 + Math.sin(t * 1.5 * swaySpeed) * breathAmount;
        rawBreath.set(breathVal);
        // Head tilt: layered sinusoids for organic, non-repeating feel
        const tilt1 = Math.sin(t * 0.5 * swaySpeed) * 0.6;
        const tilt2 = Math.sin(t * 1.3 * swaySpeed) * 0.3;
        const tilt3 = Math.sin(t * 0.3 * swaySpeed) * 0.1;
        const tiltVal = (tilt1 + tilt2 + tilt3) * headTiltAmount;
        rawHeadTilt.set(tiltVal);
        // Head nudge X/Y: different frequencies from body for independence
        const headXVal = (Math.sin(t * 0.7 * swaySpeed) * 0.6 +
            Math.sin(t * 1.9 * swaySpeed) * 0.4) *
            headNudgeAmount;
        rawHeadX.set(headXVal);
        const headYVal = (Math.sin(t * 0.9 * swaySpeed) * 0.5 +
            Math.sin(t * 2.1 * swaySpeed) * 0.3) *
            headNudgeAmount *
            0.6;
        rawHeadY.set(headYVal);
        // On first frame, jump springs directly to skip settling animation
        if (isFirstFrame.current) {
            isFirstFrame.current = false;
            sway.jump(swayVal);
            bob.jump(bobVal);
            breath.jump(breathVal);
            headTilt.jump(tiltVal);
            headX.jump(headXVal);
            headY.jump(headYVal);
        }
        rafRef.current = requestAnimationFrame(animate);
    }, [
        rawSway, rawBob, rawBreath, rawHeadTilt, rawHeadX, rawHeadY,
        sway, bob, breath, headTilt, headX, headY,
        swayAmount, swaySpeed, breathAmount, headTiltAmount, headNudgeAmount, phaseOffset,
    ]);
    useEffect(() => {
        if (!enabled || shouldReduceMotion) {
            rawSway.set(0);
            rawBob.set(0);
            rawBreath.set(1);
            rawHeadTilt.set(0);
            rawHeadX.set(0);
            rawHeadY.set(0);
            return;
        }
        startTimeRef.current = null;
        isFirstFrame.current = true;
        rafRef.current = requestAnimationFrame(animate);
        return () => cancelAnimationFrame(rafRef.current);
    }, [enabled, shouldReduceMotion, animate, rawSway, rawBob, rawBreath, rawHeadTilt, rawHeadX, rawHeadY]);
    return { sway, bob, breath, headTilt, headX, headY };
}

export { useIdleAnimation };
