import React, { useEffect, useState, useRef } from 'react';
import * as THREE from 'three';
import { useFrame, useThree } from '@react-three/fiber';
import { usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';

interface MaterialAnimatorProps {
    matRef: React.RefObject<THREE.Mesh>;
    material: MaterialSchema;
    currentSpeed: number;
    onAnimationComplete?: () => void;
}

function MaterialAnimator({
    matRef,
    material,
    currentSpeed,
    onAnimationComplete
}: MaterialAnimatorProps) {
    const { scene } = useThree();
    const [targetPosition, setTargetPosition] = useState<THREE.Vector3 | null>(null);
    const [isAnimating, setIsAnimating] = useState(false);
    const { conveyorStore } = useSceneContext();
    const { getConveyorById } = conveyorStore();
    const animationState = useRef({
        startTime: 0,
        startPosition: new THREE.Vector3(),
        totalDistance: 0,
        pausedTime: 0,
        isPaused: false,
        lastFrameTime: 0
    });

    const { isPlaying } = usePlayButtonStore();
    const { isPaused: isGlobalPaused } = usePauseButtonStore();

    const conveyor = getConveyorById(material.current.modelUuid);
    const shouldPause = isGlobalPaused || material.isPaused || conveyor?.isPaused;

    const getWorldPosition = (uuid: string): THREE.Vector3 | null => {
        const obj = scene.getObjectByProperty('uuid', uuid);
        if (!obj) return null;
        const position = new THREE.Vector3();
        obj.getWorldPosition(position);
        return position;
    };

    useEffect(() => {
        if (!isPlaying || !material.next?.pointUuid) {
            if (material.current.pointUuid) {
                const newTarget = getWorldPosition(material.current.pointUuid);
                if (newTarget && matRef.current && !material.isPaused) {
                    animationState.current.startPosition.copy(matRef.current.position);
                    animationState.current.totalDistance = animationState.current.startPosition.distanceTo(newTarget);
                    animationState.current.startTime = performance.now() - animationState.current.pausedTime;
                    animationState.current.pausedTime = 0;
                    animationState.current.isPaused = false;
                    setTargetPosition(newTarget);
                    setIsAnimating(true);
                }
            } else {
                setIsAnimating(false);
            }
            return;
        }
        const newTarget = getWorldPosition(material.next.pointUuid);
        if (newTarget && matRef.current && !material.isPaused) {
            animationState.current.startPosition.copy(matRef.current.position);
            animationState.current.totalDistance = animationState.current.startPosition.distanceTo(newTarget);
            animationState.current.startTime = performance.now() - animationState.current.pausedTime;
            animationState.current.pausedTime = 0;
            animationState.current.isPaused = false;
            setTargetPosition(newTarget);
            setIsAnimating(true);
        }
    }, [material, isPlaying]);

    useEffect(() => {
        if (shouldPause) {
            // Pause the animation
            animationState.current.isPaused = true;
            setIsAnimating(false);
            animationState.current.pausedTime = performance.now() - animationState.current.startTime;
        } else {
            // Resume the animation
            animationState.current.isPaused = false;
            if (isPlaying && targetPosition && !isAnimating) {
                animationState.current.startTime = performance.now() - animationState.current.pausedTime;
                setIsAnimating(true);
            }
        }
    }, [shouldPause, isPlaying]);

    useFrame(() => {
        if (!matRef.current || !targetPosition || !isAnimating || animationState.current.isPaused || !isPlaying) {
            return;
        }

        const currentTime = performance.now();
        const elapsed = (currentTime - animationState.current.startTime) / 1000;
        const progress = Math.min(1, (currentSpeed * elapsed) / animationState.current.totalDistance);

        matRef.current.position.lerpVectors(
            animationState.current.startPosition,
            targetPosition,
            progress
        );

        if (progress >= 1) {
            matRef.current.position.copy(targetPosition);
            setIsAnimating(false);
            onAnimationComplete?.();
            animationState.current = {
                startTime: 0,
                startPosition: new THREE.Vector3(),
                totalDistance: 0,
                pausedTime: 0,
                isPaused: false,
                lastFrameTime: 0
            };
        }
    });

    return null;
}

export default React.memo(MaterialAnimator);