import React, { useEffect, useRef, useState } from 'react'
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import IKInstance from '../ikInstance/ikInstance';
import RoboticArmAnimator from '../animator/roboticArmAnimator';
import MaterialAnimator from '../animator/materialAnimator';
import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_1.glb";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore';
import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';

function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {

    const [currentPhase, setCurrentPhase] = useState<(string)>("init");
    const [path, setPath] = useState<[number, number, number][]>([]);
    const [ikSolver, setIkSolver] = useState<any>(null);
    const { scene } = useThree();
    const restPosition = new THREE.Vector3(0, 1.75, -1.6);
    const targetBone = "Target";
    const groupRef = useRef<any>(null);
    const pauseTimeRef = useRef<number | null>(null);
    const isPausedRef = useRef<boolean>(false);
    const isSpeedRef = useRef<any>(null);
    const isIdleRef = useRef<boolean>(false);
    let startTime: number;

    const { setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore();
    const { setIsVisible } = useMaterialStore();
    const { selectedProduct } = useSelectedProduct();
    const { getActionByUuid } = useProductStore();
    const { triggerPointActions } = useTriggerHandler();
    const { isPlaying } = usePlayButtonStore();
    const { isReset } = useResetButtonStore();
    const { isPaused } = usePauseButtonStore();
    const { speed } = useAnimationPlaySpeed();

    const activeSecondsElapsed = useRef(0);
    const activeTimerId = useRef<ReturnType<typeof setInterval> | null>(null);

    const idleSecondsElapsed = useRef(0);
    const idleTimerId = useRef<ReturnType<typeof setInterval> | null>(null);

    function firstFrame() {
        startTime = performance.now();
        step();
    }

    function step() {
        if (isPausedRef.current) {
            if (!pauseTimeRef.current) {
                pauseTimeRef.current = performance.now();
            }
            requestAnimationFrame(() => step());
            return;
        }
        if (pauseTimeRef.current) {
            const pauseDuration = performance.now() - pauseTimeRef.current;
            startTime += pauseDuration;
            pauseTimeRef.current = null;
        }
        const elapsedTime = performance.now() - startTime;
        if (elapsedTime < 1000) {
            // Wait until 1500ms has passed
            requestAnimationFrame(step);
            return;
        }
        if (currentPhase === "picking") {
            setArmBotActive(armBot.modelUuid, true);
            setArmBotState(armBot.modelUuid, "running");
            setCurrentPhase("start-to-end");
            startTime = 0
            const startPoint = armBot.point.actions[0].process.startPoint;
            const endPoint = armBot.point.actions[0].process.endPoint;
            if (startPoint && endPoint) {
                let curve = createCurveBetweenTwoPoints(
                    new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]),
                    new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]));
                if (curve) {
                    logStatus(armBot.modelUuid, "picking the object");
                    setPath(curve.points.map(point => [point.x, point.y, point.z]))

                    if (armBot.currentAction) {
                        setIsVisible(armBot.currentAction.materialId || '', false);
                    }
                }
            }
            logStatus(armBot.modelUuid, "Moving armBot from start point to end position.")
        } else if (currentPhase === "dropping") {
            setArmBotActive(armBot.modelUuid, true);
            setArmBotState(armBot.modelUuid, "running");
            setCurrentPhase("end-to-rest");
            startTime = 0;
            const endPoint = armBot.point.actions[0].process.endPoint;
            if (endPoint) {

                let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition);
                if (curve) {
                    logStatus(armBot.modelUuid, "dropping the object");
                    setPath(curve.points.map(point => [point.x, point.y, point.z]));

                    if (armBot.currentAction) {
                        setIsVisible(armBot.currentAction.materialId || '', true);
                    }

                    if (armBot.currentAction) {
                        const action = getActionByUuid(selectedProduct.productId, armBot.currentAction.actionUuid);
                        if (action && armBot.currentAction.materialId) {
                            triggerPointActions(action, armBot.currentAction.materialId)
                            removeCurrentAction(armBot.modelUuid)
                        }
                    }
                }
            }
            logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.")
        }
    }

    useEffect(() => {

        isPausedRef.current = isPaused;
    }, [isPaused]);

    useEffect(() => {

        isSpeedRef.current = speed;
    }, [speed]);

    useEffect(() => {
        if (isReset || !isPlaying) {
            logStatus(armBot.modelUuid, "Simulation Play Reset Successfully")
            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("init");
            setPath([])
            setIkSolver(null);
            removeCurrentAction(armBot.modelUuid)
            isPausedRef.current = false
            pauseTimeRef.current = null
            startTime = 0
            clearInterval(activeTimerId.current!);
            clearInterval(idleTimerId.current!);
            activeTimerId.current = null;
            activeSecondsElapsed.current = 0;
            idleSecondsElapsed.current = 0;
            idleTimerId.current = null;
            const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone
            );
            if (targetBones && isPlaying) {
                let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
                if (curve) {
                    setPath(curve.points.map(point => [point.x, point.y, point.z]));
                    logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
                }
            }
        }
    }, [isReset, isPlaying])

    useEffect(() => {
        if (!isPlaying) return;

        const intervalMs = 1000 / isSpeedRef.current;
        console.log('intervalMs: ', intervalMs);

        if (!armBot.isActive && armBot.state == "idle" && (currentPhase == "rest" || currentPhase == "init") && !isIdleRef.current) {
            isIdleRef.current = true

            // Stop the timer
            // 🚨 1. Clear Active Timer
            if (activeTimerId.current) {
                clearInterval(activeTimerId.current);
                activeTimerId.current = null;
            }
            console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current} seconds`);

            // 🚨 2. Reset active timer seconds after logging
            activeSecondsElapsed.current = 0;

            // 🚨 3. Start Idle Timer (clean old idle timer first)
            if (idleTimerId.current) {
                clearInterval(idleTimerId.current);
                idleTimerId.current = null;
            }

            idleSecondsElapsed.current = 0;
            idleTimerId.current = setInterval(() => {
                if (!isPausedRef.current) {
                    idleSecondsElapsed.current += 1;
                    console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current} seconds`);
                }
            }, intervalMs);
        } else if (armBot.isActive && armBot.state != "idle" && currentPhase !== "rest" && armBot.currentAction && isIdleRef.current) {
            isIdleRef.current = false

            if (armBot.currentAction) {
                // 🚨 Clear Idle Timer
                if (idleTimerId.current) {
                    clearInterval(idleTimerId.current);
                    idleTimerId.current = null;
                }
                console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current} seconds`);
                idleSecondsElapsed.current = 0;

                // 🚨 Start Active Timer
                if (activeTimerId.current) {
                    clearInterval(activeTimerId.current);
                }
                activeSecondsElapsed.current = 0;
                activeTimerId.current = setInterval(() => {
                    if (!isPausedRef.current) {
                        activeSecondsElapsed.current += 1
                        console.log(`🕒 Active Timer: ${activeSecondsElapsed.current} seconds`);
                    }
                }, intervalMs);
            }
        }

    }, [armBot, currentPhase, isPlaying])


    // useEffect(() => {
    //     if (!isPlaying) return;
    //     const now = () => performance.now();


    //     const startActiveTimer = () => {
    //         let lastTime = now();

    //         const update = () => {
    //             if (!isPausedRef.current) {
    //                 const currentTime = now();
    //                 const delta = currentTime - lastTime;
    //                 activeSecondsElapsed.current += delta / 1000;
    //                 console.log(`🕒 Active Timer: ${activeSecondsElapsed.current.toFixed(2)} seconds`);
    //                 lastTime = currentTime;
    //             } else {

    //                 lastTime = now();
    //             }

    //             if (!isIdleRef.current) {
    //                 requestAnimationFrame(update);
    //             }
    //         };

    //         activeSecondsElapsed.current = 0;
    //         update();
    //     };

    //     const startIdleTimer = () => {
    //         let lastTime = now();

    //         const update = () => {
    //             if (!isPausedRef.current) {
    //                 const currentTime = now();
    //                 const delta = currentTime - lastTime;
    //                 idleSecondsElapsed.current += delta / 1000;
    //                 console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current.toFixed(2)} seconds`);
    //                 lastTime = currentTime;
    //             } else {
    //                 lastTime = now();
    //             }

    //             if (isIdleRef.current) {
    //                 requestAnimationFrame(update);
    //             }
    //         };

    //         idleSecondsElapsed.current = 0;
    //         update();
    //     };

    //     // State transition logic
    //     if (!armBot.isActive && armBot.state === "idle" && (currentPhase === "rest" || currentPhase === "init") && !isIdleRef.current) {
    //         isIdleRef.current = true;
    //         console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current.toFixed(2)} seconds`);
    //         startIdleTimer();
    //     }
    //     else if (armBot.isActive && armBot.state !== "idle" && currentPhase !== "rest" && armBot.currentAction && isIdleRef.current) {
    //         isIdleRef.current = false;
    //         console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current.toFixed(2)} seconds`);
    //         startActiveTimer();
    //     }

    // }, [armBot, currentPhase, isPlaying, isIdleRef.current, isPausedRef.current]);


    useEffect(() => {
        const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid);
        if (targetMesh) {
            targetMesh.visible = (!isPlaying)
        }
        const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
        if (!isReset && isPlaying) {
            //Moving armBot from initial point to rest position.
            if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
                if (targetBones) {
                    setArmBotActive(armBot.modelUuid, true)
                    setArmBotState(armBot.modelUuid, "running")
                    setCurrentPhase("init-to-rest");
                    let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
                    if (curve) {
                        setPath(curve.points.map(point => [point.x, point.y, point.z]));
                    }
                }
                logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
            }
            //Waiting for trigger.
            else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && !armBot.currentAction) {

                logStatus(armBot.modelUuid, "Waiting to trigger CurrentAction")
            }
            //Moving to pickup point
            else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && armBot.currentAction) {
                if (armBot.currentAction) {

                    setArmBotActive(armBot.modelUuid, true);
                    setArmBotState(armBot.modelUuid, "running");
                    setCurrentPhase("rest-to-start");
                    // // 🚨 Clear Idle Timer
                    // if (idleTimerId.current) {
                    //     clearInterval(idleTimerId.current);
                    //     idleTimerId.current = null;
                    // }
                    // console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current} seconds`);
                    // idleSecondsElapsed.current = 0;

                    // // 🚨 Start Active Timer
                    // if (activeTimerId.current) {
                    //     clearInterval(activeTimerId.current);
                    // }
                    // activeSecondsElapsed.current = 0;
                    // activeTimerId.current = setInterval(() => {
                    //     if (!isPausedRef.current) {
                    //         activeSecondsElapsed.current += 1;
                    //         console.log(`🕒 Active Timer: ${activeSecondsElapsed.current} seconds`);
                    //     }
                    // }, 1000);

                    const startPoint = armBot.point.actions[0].process.startPoint;
                    if (startPoint) {
                        let curve = createCurveBetweenTwoPoints(targetBones.position, new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]));
                        if (curve) {
                            setPath(curve.points.map(point => [point.x, point.y, point.z]));
                        }
                    }
                }
                logStatus(armBot.modelUuid, "Moving armBot from rest point to start position.")
            }
            // Moving to Pick to Drop position
            else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) {
                requestAnimationFrame(firstFrame);
            }
            //Moving to drop point to restPosition
            else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) {
                requestAnimationFrame(firstFrame);
            }
        } else {
            logStatus(armBot.modelUuid, "Simulation Play Exited")
            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("init");
            setIkSolver(null);
            setPath([])
            isPausedRef.current = false
            pauseTimeRef.current = null
            isPausedRef.current = false
            startTime = 0
            clearInterval(activeTimerId.current!);
            clearInterval(idleTimerId.current!);
            activeTimerId.current = null;
            activeSecondsElapsed.current = 0;
            idleSecondsElapsed.current = 0;
            idleTimerId.current = null;
            removeCurrentAction(armBot.modelUuid)
        }

    }, [currentPhase, armBot, isPlaying, isReset, ikSolver])


    function createCurveBetweenTwoPoints(p1: any, p2: any) {
        const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5);
        // mid.y += 0.5;
        const points = [p1, mid, p2];
        return new THREE.CatmullRomCurve3(points);
    }


    const HandleCallback = () => {
        if (armBot.isActive && armBot.state == "running" && currentPhase == "init-to-rest") {
            logStatus(armBot.modelUuid, "Callback triggered: rest");
            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("rest");
            setPath([])
        }
        else if (armBot.isActive && armBot.state == "running" && currentPhase == "rest-to-start") {
            logStatus(armBot.modelUuid, "Callback triggered: pick.");
            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("picking");
            setPath([])
        }
        else if (armBot.isActive && armBot.state == "running" && currentPhase == "start-to-end") {
            logStatus(armBot.modelUuid, "Callback triggered: drop.");
            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("dropping");
            setPath([])
        }
        else if (armBot.isActive && armBot.state == "running" && currentPhase == "end-to-rest") {
            logStatus(armBot.modelUuid, "Callback triggered: rest, cycle completed.");
            // Stop the timer
            // 🚨 1. Clear Active Timer
            // if (activeTimerId.current) {
            //     clearInterval(activeTimerId.current);
            //     activeTimerId.current = null;
            // }
            // console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current} seconds`);

            // // 🚨 2. Reset active timer seconds after logging
            // activeSecondsElapsed.current = 0;

            // // 🚨 3. Start Idle Timer (clean old idle timer first)
            // if (idleTimerId.current) {
            //     clearInterval(idleTimerId.current);
            //     idleTimerId.current = null;
            // }

            // idleSecondsElapsed.current = 0;
            // idleTimerId.current = setInterval(() => {
            //     if (!isPausedRef.current) {
            //         idleSecondsElapsed.current += 1;
            //         console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current} seconds`);
            //     }
            // }, 1000);


            setArmBotActive(armBot.modelUuid, false)
            setArmBotState(armBot.modelUuid, "idle")
            setCurrentPhase("rest");
            setPath([])
        }
    }
    const logStatus = (id: string, status: string) => {
    }

    return (
        <>
            {!isReset && isPlaying && (
                <>
                    <IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} />
                    <RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot}
                        logStatus={logStatus} path={path} currentPhase={currentPhase} />
                </>
            )}
            <MaterialAnimator ikSolver={ikSolver} armBot={armBot} currentPhase={currentPhase} />
        </>
    )
}

export default RoboticArmInstance;
