import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';

import HumanAnimator from '../animator/humanAnimator';

function HumanInstance({ human }: { human: HumanStatus }) {
    const { navMesh } = useNavMesh();
    const { isPlaying } = usePlayButtonStore();
    const { materialStore, armBotStore, conveyorStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext();
    const { removeMaterial, setEndTime } = materialStore();
    const { getStorageUnitById } = storageUnitStore();
    const { getArmBotById } = armBotStore();
    const { getConveyorById } = conveyorStore();
    const { getVehicleById } = vehicleStore();
    const { triggerPointActions } = useTriggerHandler();
    const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
    const { selectedProductStore } = useProductContext();
    const { selectedProduct } = selectedProductStore();
    const { humans, setHumanActive, setHumanState, setHumanPicking, clearCurrentMaterials, setHumanLoad, decrementHumanLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore();

    const [currentPhase, setCurrentPhase] = useState<string>('init');
    const [path, setPath] = useState<[number, number, number][]>([]);
    const pauseTimeRef = useRef<number | null>(null);
    const idleTimeRef = useRef<number>(0);
    const activeTimeRef = useRef<number>(0);
    const isPausedRef = useRef<boolean>(false);
    const isSpeedRef = useRef<number>(0);
    let startTime: number;
    let fixedInterval: number;
    const { speed } = useAnimationPlaySpeed();
    const { isPaused } = usePauseButtonStore();
    const previousTimeRef = useRef<number | null>(null);
    const animationFrameIdRef = useRef<number | null>(null);

    useEffect(() => {
        isPausedRef.current = isPaused;
    }, [isPaused]);

    useEffect(() => {
        isSpeedRef.current = speed;
    }, [speed]);

    const computePath = useCallback(
        (start: any, end: any) => {
            try {
                const navMeshQuery = new NavMeshQuery(navMesh);
                const { path: segmentPath } = navMeshQuery.computePath(start, end);
                if (
                    segmentPath.length > 0 &&
                    Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) &&
                    Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)
                ) {
                    return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
                } else {
                    console.log("There is no path here...Choose valid path")
                    const { path: segmentPaths } = navMeshQuery.computePath(start, start);
                    return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
                }
            } catch {
                console.error("Failed to compute path");
                return [];
            }
        }, [navMesh]);

    function humanStatus(modelId: string, status: string) {
        console.log(`${modelId} , ${status}`);
    }

    function reset() {
        setCurrentPhase('init');
        setHumanActive(human.modelUuid, false);
        setHumanPicking(human.modelUuid, false);
        setHumanState(human.modelUuid, 'idle');
        setHumanLoad(human.modelUuid, 0);
        setPath([]);
        startTime = 0;
        isPausedRef.current = false;
        pauseTimeRef.current = 0;
        resetTime(human.modelUuid)
        activeTimeRef.current = 0
        idleTimeRef.current = 0
        previousTimeRef.current = null
        if (animationFrameIdRef.current !== null) {
            cancelAnimationFrame(animationFrameIdRef.current)
            animationFrameIdRef.current = null
        }
    }

    useEffect(() => {
        if (isPlaying) {
            if (!human.point.action.pickUpPoint || !human.point.action.dropPoint) return;

            if (!human.isActive && human.state === 'idle' && currentPhase === 'init') {
                const toPickupPath = computePath(
                    new THREE.Vector3(human?.position[0], human?.position[1], human?.position[2]),
                    new THREE.Vector3(
                        human?.point?.action?.pickUpPoint?.position?.[0] ?? 0,
                        human?.point?.action?.pickUpPoint?.position?.[1] ?? 0,
                        human?.point?.action?.pickUpPoint?.position?.[2] ?? 0
                    )
                );
                setPath(toPickupPath);
                setCurrentPhase('init-pickup');
                setHumanState(human.modelUuid, 'running');
                setHumanPicking(human.modelUuid, false);
                setHumanActive(human.modelUuid, true);
                humanStatus(human.modelUuid, 'Started from init, heading to pickup');
                return;
            }

        }
        else {
            reset()
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [human, currentPhase, path, isPlaying]);

    function handleCallBack() {
        if (currentPhase === 'init-pickup') {
            setCurrentPhase('picking');
        } else if (currentPhase === 'pickup-drop') {
        } else if (currentPhase === 'drop-pickup') {
        }
    }

    function startUnloadingProcess() {
    }

    return (
        <>

            <HumanAnimator
                path={path}
                handleCallBack={handleCallBack}
                currentPhase={currentPhase}
                human={human}
                reset={reset}
                startUnloadingProcess={startUnloadingProcess}
            />

        </>
    )
}

export default HumanInstance