import { useCallback, useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore, useAnimationPlaySpeed } from "../../../../../store/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";

interface DelayInstance {
    initialDelay: number;
    delayEndTime: number;
    materialId?: string;
    action: ConveyorAction;
    isPaused: boolean;
    remainingTime: number;
    lastUpdateTime: number;
    elapsedTime: number;
}

export function useDelayHandler() {
    const { isPlaying } = usePlayButtonStore();
    const { isPaused } = usePauseButtonStore();
    const { isReset } = useResetButtonStore();
    const { speed } = useAnimationPlaySpeed();
    const { materialStore } = useSceneContext();
    const { setIsPaused } = materialStore();
    const activeDelays = useRef<Map<string, DelayInstance>>(new Map());
    const lastUpdateTimeRef = useRef<number>(performance.now());

    const cleanupDelay = useCallback(() => {
        activeDelays.current.clear();
    }, []);

    useEffect(() => {
        if (isReset) {
            cleanupDelay();
        }
    }, [isReset, cleanupDelay]);

    const delayLogStatus = (materialUuid: string, status: string) => {
        echo.info(`${materialUuid}, ${status}`);
    };

    useFrame(() => {
        const currentTime = performance.now();
        const deltaTime = currentTime - lastUpdateTimeRef.current;
        lastUpdateTimeRef.current = currentTime;
        const completedDelays: string[] = [];

        activeDelays.current.forEach((delay, key) => {
            if (isPaused && !delay.isPaused) {
                delay.remainingTime = Math.max(0, delay.delayEndTime - currentTime);
                delay.isPaused = true;
            } else if (!isPaused && delay.isPaused) {
                delay.delayEndTime = currentTime + delay.remainingTime;
                delay.isPaused = false;
                delay.lastUpdateTime = currentTime;
                delay.elapsedTime = 0;
            } else if (!delay.isPaused && isPlaying) {
                delay.elapsedTime += deltaTime * speed;

                if (delay.elapsedTime >= delay.initialDelay) {
                    if (delay.materialId) {
                        delayLogStatus(delay.materialId, `Delay completed`);
                        setIsPaused(delay.materialId, false);
                    }
                    completedDelays.push(key);
                }
            }
        });

        completedDelays.forEach(key => {
            activeDelays.current.delete(key);
        });
    });

    const handleDelay = useCallback((action: ConveyorAction, materialId?: string) => {
        if (!action || action.actionType !== 'delay' || !materialId) return;

        const delayMs = (action.delay || 0) * 1000;
        if (delayMs <= 0) return;

        const key = materialId ? `${materialId}-${action.actionUuid}` : action.actionUuid;

        if (activeDelays.current.has(key)) {
            activeDelays.current.delete(key);
        }

        const now = performance.now();
        activeDelays.current.set(key, {
            initialDelay: delayMs,
            delayEndTime: now + delayMs,
            materialId,
            action,
            isPaused: false,
            remainingTime: 0,
            lastUpdateTime: now,
            elapsedTime: 0
        });

        delayLogStatus(materialId, `Started ${delayMs / 1000}s delay`);
        setIsPaused(materialId, true);
    }, [isPlaying]);

    useEffect(() => {
        return () => {
            cleanupDelay();
        };
    }, [cleanupDelay]);

    return {
        handleDelay,
        cleanupDelay
    };
}