import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { SkeletonUtils } from "three-stdlib";
import { useContextActionStore, useSocketStore, useToggleView } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap";

// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";

const DuplicationControls3D = () => {
    const { camera, controls, gl, scene, pointer, raycaster } = useThree();
    const { toggleView } = useToggleView();
    const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
    const { socket } = useSocketStore();
    const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
    const { push3D } = undoRedo3DStore();
    const { addEvent } = eventStore();
    const { projectId } = useParams();
    const { assets, addAsset, updateAsset, removeAsset, getAssetById, selectedAssets, setSelectedAssets, duplicatedObjects, setDuplicatedObjects, setPastedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { userId, organization } = getUserData();

    const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
    const [axisConstraint, setAxisConstraint] = useState<"x" | "z" | null>(null);
    const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
    const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
    const [isDuplicating, setIsDuplicating] = useState(false);
    const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
    const { contextAction, setContextAction } = useContextActionStore()
    const fineMoveBaseRef = useRef<THREE.Vector3 | null>(null);
    const lastPointerPositionRef = useRef<THREE.Vector3 | null>(null);
    const wasShiftHeldRef = useRef(false);

    const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
        const pointPosition = new THREE.Vector3().copy(point.position);
        return new THREE.Vector3().subVectors(pointPosition, hitPoint);
    }, []);

    useEffect(() => {
        if (contextAction === "duplicateAsset") {
            setContextAction(null);
            duplicateSelection()
        }
    }, [contextAction])

    useEffect(() => {
        if (!camera || !scene || toggleView) return;
        const canvasElement = gl.domElement;
        canvasElement.tabIndex = 0;

        let isPointerMoving = false;

        const onPointerDown = (event: PointerEvent) => {
            isPointerMoving = false;
            if (event.button === 0) mouseButtonsDown.current.left = true;
            if (event.button === 2) mouseButtonsDown.current.right = true;
        };

        const onPointerMove = () => {
            isPointerMoving = true;
        };

        const onPointerUp = (event: PointerEvent) => {
            if (event.button === 0) mouseButtonsDown.current.left = false;
            if (event.button === 2) mouseButtonsDown.current.right = false;

            if (!isPointerMoving && duplicatedObjects.length > 0 && event.button === 0) {
                event.preventDefault();
                addDuplicatedAssets();
            }
            if (!isPointerMoving && duplicatedObjects.length > 0 && event.button === 2) {
                event.preventDefault();
                clearSelection();
                duplicatedObjects.forEach((obj: THREE.Object3D) => {
                    removeAsset(obj.userData.modelUuid);
                });
            }
            setKeyEvent("");
        };

        const onKeyDown = (event: KeyboardEvent) => {
            const keyCombination = detectModifierKeys(event);

            if (isDuplicating && duplicatedObjects.length > 0) {
                if (event.key.toLowerCase() === 'x') {
                    setAxisConstraint(prev => prev === 'x' ? null : 'x');
                    event.preventDefault();
                    return;
                }
                if (event.key.toLowerCase() === 'z') {
                    setAxisConstraint(prev => prev === 'z' ? null : 'z');
                    event.preventDefault();
                    return;
                }
            }

            if (keyCombination !== keyEvent) {
                if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
                    setKeyEvent(keyCombination);
                } else {
                    setKeyEvent("");
                }
            }

            if (keyCombination === "Ctrl+D" && movedObjects.length === 0 && rotatedObjects.length === 0) {
                duplicateSelection();
            }
            if (keyCombination === "ESCAPE" && duplicatedObjects.length > 0) {
                event.preventDefault();
                clearSelection();
                duplicatedObjects.forEach((obj: THREE.Object3D) => {
                    removeAsset(obj.userData.modelUuid);
                });
            }
        };

        const onKeyUp = (event: KeyboardEvent) => {
            const keyCombination = detectModifierKeys(event);

            if (keyCombination === "") {
                setKeyEvent("");
            } else if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
                setKeyEvent(keyCombination);
            }
            if (duplicatedObjects[0] && keyEvent !== "" && keyCombination === '') {
                const intersectionPoint = new THREE.Vector3();
                raycaster.setFromCamera(pointer, camera);
                const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
                if (hit) {
                    const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
                    if (model) {
                        const newOffset = calculateDragOffset(model, intersectionPoint);
                        setDragOffset(newOffset);
                    }
                }
            }
        };

        if (!toggleView) {
            canvasElement.addEventListener("pointerdown", onPointerDown);
            canvasElement.addEventListener("pointermove", onPointerMove);
            canvasElement.addEventListener("pointerup", onPointerUp);
            canvasElement.addEventListener("keydown", onKeyDown);
            canvasElement.addEventListener("keyup", onKeyUp);
        }

        return () => {
            canvasElement.removeEventListener("pointerdown", onPointerDown);
            canvasElement.removeEventListener("pointermove", onPointerMove);
            canvasElement.removeEventListener("pointerup", onPointerUp);
            canvasElement.removeEventListener("keydown", onKeyDown);
            canvasElement.addEventListener("keyup", onKeyUp);
        };
    }, [assets, camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, rotatedObjects, keyEvent]);

    useFrame(() => {
        if (!isDuplicating || duplicatedObjects.length === 0) return;

        const intersectionPoint = new THREE.Vector3();
        raycaster.setFromCamera(pointer, camera);
        const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);

        if (hit) {
            if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) {
                const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
                if (model) {
                    const newOffset = calculateDragOffset(model, intersectionPoint);
                    setDragOffset(newOffset);
                }
                return;
            }

            if (dragOffset) {
                const rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
                const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
                const baseNewPosition = handleAssetPositionSnap({ rawBasePosition, intersectionPoint, model, axisConstraint, keyEvent, fineMoveBaseRef, lastPointerPositionRef, wasShiftHeldRef });

                duplicatedObjects.forEach((duplicatedObject: THREE.Object3D) => {
                    if (duplicatedObject.userData.modelUuid) {
                        const initialPosition = initialPositions[duplicatedObject.userData.modelUuid];

                        if (initialPosition) {

                            const relativeOffset = new THREE.Vector3().subVectors(
                                initialPosition,
                                initialPositions[duplicatedObjects[0].userData.modelUuid]
                            );
                            const model = scene.getObjectByProperty("uuid", duplicatedObject.userData.modelUuid);

                            const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
                            const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z];

                            if (model) {
                                model.position.set(...positionArray);
                            }
                        }
                    }
                });
            }
        }
    });

    useEffect(() => {
        if (duplicatedObjects.length > 0) {
            const intersectionPoint = new THREE.Vector3();
            raycaster.setFromCamera(pointer, camera);
            const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
            if (hit) {
                const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
                if (model) {
                    const newOffset = calculateDragOffset(model, intersectionPoint);
                    setDragOffset(newOffset);
                }
            }
        }
    }, [axisConstraint, camera, duplicatedObjects])

    const duplicateSelection = useCallback(() => {
        if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
            const positions: Record<string, THREE.Vector3> = {};

            const newDuplicatedObjects = selectedAssets.map((obj: any) => {
                const clone = SkeletonUtils.clone(obj);
                clone.userData.modelUuid = THREE.MathUtils.generateUUID();
                positions[clone.userData.modelUuid] = new THREE.Vector3().copy(obj.position);
                return clone;
            });

            setDuplicatedObjects(newDuplicatedObjects);
            setInitialPositions(positions);

            raycaster.setFromCamera(pointer, camera);
            const intersectionPoint = new THREE.Vector3();
            const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);

            if (hit) {
                const offset = calculateDragOffset(selectedAssets[0], hit);
                setDragOffset(offset);
            }

            setIsDuplicating(true);

            newDuplicatedObjects.forEach((obj: THREE.Object3D) => {
                const asset: Asset = {
                    modelUuid: obj.userData.modelUuid,
                    modelName: obj.userData.modelName,
                    assetId: obj.userData.assetId,
                    position: [obj.position.x, 0, obj.position.z],
                    rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
                    isLocked: false,
                    isVisible: true,
                    isCollidable: false,
                    opacity: 0.5,
                };
                addAsset(asset);
            });
        }
    }, [selectedAssets, duplicatedObjects]);


    const addDuplicatedAssets = () => {
        if (duplicatedObjects.length === 0) return;

        const undoActions: UndoRedo3DAction[] = [];
        const assetsToDuplicate: AssetData[] = [];

        duplicatedObjects.forEach(async (duplicatedAsset: THREE.Object3D) => {
            if (duplicatedAsset) {
                const assetUuid = duplicatedAsset.userData.modelUuid;
                const asset = getAssetById(assetUuid);
                const model = scene.getObjectByProperty("uuid", duplicatedAsset.userData.modelUuid);
                if (!asset || !model) return;
                const position = new THREE.Vector3().copy(model.position);

                const newFloorItem: Types.FloorItemType = {
                    modelUuid: duplicatedAsset.userData.modelUuid,
                    modelName: duplicatedAsset.userData.modelName,
                    assetId: duplicatedAsset.userData.assetId,
                    position: [position.x, position.y, position.z],
                    rotation: { x: asset.rotation[0], y: asset.rotation[1], z: asset.rotation[2] },
                    isLocked: false,
                    isVisible: true,
                };

                let updatedEventData = null;

                if (duplicatedAsset.userData.eventData) {
                    updatedEventData = JSON.parse(JSON.stringify(duplicatedAsset.userData.eventData));
                    updatedEventData.modelUuid = newFloorItem.modelUuid;

                    const eventData: any = {
                        type: duplicatedAsset.userData.eventData.type,
                        subType: duplicatedAsset.userData.eventData.subType,
                    };

                    if (duplicatedAsset.userData.eventData.type === "Conveyor") {
                        const ConveyorEvent: ConveyorEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: 'transfer',
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            speed: 1,
                            points: updatedEventData.points.map((point: any, index: number) => ({
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [point.position[0], point.position[1], point.position[2]],
                                rotation: [point.rotation[0], point.rotation[1], point.rotation[2]],
                                action: {
                                    actionUuid: THREE.MathUtils.generateUUID(),
                                    actionName: `Action 1`,
                                    actionType: 'default',
                                    material: 'Default Material',
                                    delay: 0,
                                    spawnInterval: 5,
                                    spawnCount: 1,
                                    triggers: []
                                }
                            }))
                        };
                        addEvent(ConveyorEvent);
                        eventData.points = ConveyorEvent.points.map(point => ({
                            uuid: point.uuid,
                            position: point.position,
                            rotation: point.rotation
                        }));

                    } else if (duplicatedAsset.userData.eventData.type === "Vehicle") {
                        const vehicleEvent: VehicleEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "vehicle",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            speed: 1,
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                action: {
                                    actionUuid: THREE.MathUtils.generateUUID(),
                                    actionName: "Action 1",
                                    actionType: "travel",
                                    unLoadDuration: 5,
                                    loadCapacity: 1,
                                    steeringAngle: 0,
                                    pickUpPoint: null,
                                    unLoadPoint: null,
                                    paths: {
                                        initPickup: [],
                                        pickupDrop: [],
                                        dropPickup: [],
                                    },
                                    triggers: []
                                }
                            }
                        };
                        addEvent(vehicleEvent);
                        eventData.point = {
                            uuid: vehicleEvent.point.uuid,
                            position: vehicleEvent.point.position,
                            rotation: vehicleEvent.point.rotation
                        };

                    } else if (duplicatedAsset.userData.eventData.type === "ArmBot") {
                        const roboticArmEvent: RoboticArmEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "roboticArm",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            speed: 1,
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                actions: [
                                    {
                                        actionUuid: THREE.MathUtils.generateUUID(),
                                        actionName: "Action 1",
                                        actionType: "pickAndPlace",
                                        process: {
                                            startPoint: null,
                                            endPoint: null
                                        },
                                        triggers: []
                                    }
                                ]
                            }
                        };
                        addEvent(roboticArmEvent);
                        eventData.point = {
                            uuid: roboticArmEvent.point.uuid,
                            position: roboticArmEvent.point.position,
                            rotation: roboticArmEvent.point.rotation
                        };

                    } else if (duplicatedAsset.userData.eventData.type === "StaticMachine") {
                        const machineEvent: MachineEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "machine",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                action: {
                                    actionUuid: THREE.MathUtils.generateUUID(),
                                    actionName: "Action 1",
                                    actionType: "process",
                                    processTime: 10,
                                    swapMaterial: "Default Material",
                                    triggers: []
                                }
                            }
                        };
                        addEvent(machineEvent);
                        eventData.point = {
                            uuid: machineEvent.point.uuid,
                            position: machineEvent.point.position,
                            rotation: machineEvent.point.rotation
                        };
                    } else if (duplicatedAsset.userData.eventData.type === "Storage") {
                        const storageEvent: StorageEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "storageUnit",
                            storageCapacity: 10,
                            storageCount: 10,
                            materialType: "Default material",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                actions: [
                                    {
                                        actionUuid: THREE.MathUtils.generateUUID(),
                                        actionName: "Action 1",
                                        actionType: "store",
                                        triggers: []
                                    }
                                ]
                            }
                        }
                        addEvent(storageEvent);
                        eventData.point = {
                            uuid: storageEvent.point.uuid,
                            position: storageEvent.point.position,
                            rotation: storageEvent.point.rotation
                        };
                    } else if (duplicatedAsset.userData.eventData.type === "Human") {
                        const humanEvent: HumanEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "human",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            speed: 1,
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                actions: [
                                    {
                                        actionUuid: THREE.MathUtils.generateUUID(),
                                        actionName: "Action 1",
                                        actionType: "worker",
                                        loadCapacity: 1,
                                        assemblyCount: 1,
                                        assemblyCondition: {
                                            conditionType: 'material',
                                            materialType: "Default material"
                                        },
                                        manufactureCount: 1,
                                        loadCount: 1,
                                        processTime: 10,
                                        triggers: []
                                    }
                                ]
                            }
                        }
                        addEvent(humanEvent);
                        eventData.point = {
                            uuid: humanEvent.point.uuid,
                            position: humanEvent.point.position,
                            rotation: humanEvent.point.rotation
                        };
                    } else if (duplicatedAsset.userData.eventData.type === "Crane") {
                        const craneEvent: CraneEventSchema = {
                            modelUuid: newFloorItem.modelUuid,
                            modelName: newFloorItem.modelName,
                            position: newFloorItem.position,
                            rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
                            state: "idle",
                            type: "crane",
                            subType: duplicatedAsset.userData.eventData.subType || '',
                            point: {
                                uuid: THREE.MathUtils.generateUUID(),
                                position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
                                rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
                                actions: [
                                    {
                                        actionUuid: THREE.MathUtils.generateUUID(),
                                        actionName: "Action 1",
                                        actionType: "pickAndDrop",
                                        maxPickUpCount: 1,
                                        triggers: []
                                    }
                                ]
                            }
                        }
                        addEvent(craneEvent);
                        eventData.point = {
                            uuid: craneEvent.point.uuid,
                            position: craneEvent.point.position,
                            rotation: craneEvent.point.rotation
                        };
                    }

                    newFloorItem.eventData = eventData;

                    const data = {
                        organization,
                        modelUuid: newFloorItem.modelUuid,
                        modelName: newFloorItem.modelName,
                        assetId: newFloorItem.assetId,
                        position: [position.x, position.y, position.z],
                        rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
                        isLocked: false,
                        isVisible: true,
                        socketId: socket.id,
                        eventData: eventData,
                        versionId: selectedVersion?.versionId || '',
                        userId,
                        projectId
                    };

                    //REST

                    // await setAssetsApi(data);

                    //SOCKET

                    socket.emit("v1:model-asset:add", data);

                    const asset: Asset = {
                        modelUuid: data.modelUuid,
                        modelName: data.modelName,
                        assetId: data.assetId,
                        position: [position.x, position.y, position.z],
                        rotation: [data.rotation.x, data.rotation.y, data.rotation.z],
                        isLocked: data.isLocked,
                        isCollidable: false,
                        isVisible: data.isVisible,
                        opacity: 1,
                        eventData: data.eventData
                    };

                    updateAsset(asset.modelUuid, asset);
                } else {
                    const data = {
                        organization,
                        modelUuid: newFloorItem.modelUuid,
                        modelName: newFloorItem.modelName,
                        assetId: newFloorItem.assetId,
                        position: [position.x, position.y, position.z],
                        rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
                        isLocked: false,
                        isVisible: true,
                        socketId: socket.id,
                        versionId: selectedVersion?.versionId || '',
                        projectId,
                        userId
                    };

                    socket.emit("v1:model-asset:add", data);

                    const asset: Asset = {
                        modelUuid: data.modelUuid,
                        modelName: data.modelName,
                        assetId: data.assetId,
                        position: [position.x, position.y, position.z],
                        rotation: [data.rotation.x, data.rotation.y, data.rotation.z],
                        isLocked: data.isLocked,
                        isCollidable: false,
                        isVisible: data.isVisible,
                        opacity: 1,
                    };

                    updateAsset(asset.modelUuid, asset);
                }

                assetsToDuplicate.push({
                    type: "Asset",
                    assetData: {
                        modelUuid: newFloorItem.modelUuid,
                        modelName: newFloorItem.modelName,
                        assetId: newFloorItem.assetId,
                        position: [position.x, position.y, position.z],
                        rotation: [duplicatedAsset.rotation.x, duplicatedAsset.rotation.y, duplicatedAsset.rotation.z],
                        isLocked: false,
                        isVisible: true,
                        isCollidable: false,
                        opacity: 1,
                        eventData: newFloorItem.eventData || undefined
                    },
                    timeStap: new Date().toISOString()
                });
            }
        });

        if (assetsToDuplicate.length === 1) {
            undoActions.push({
                module: "builder",
                actionType: "Asset-Copied",
                asset: assetsToDuplicate[0]
            });
        } else {
            undoActions.push({
                module: "builder",
                actionType: "Assets-Copied",
                assets: assetsToDuplicate
            });
        }

        push3D({
            type: 'Scene',
            actions: undoActions
        });

        echo.success("Object duplicated!");
        clearSelection();
    };

    const clearSelection = () => {
        setMovedObjects([]);
        setPastedObjects([]);
        setDuplicatedObjects([]);
        setRotatedObjects([]);
        setSelectedAssets([]);
        setIsDuplicating(false);
        setDragOffset(null);
        setAxisConstraint(null);
    };

    return null;
};

export default DuplicationControls3D;