import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useSocketStore } from "../../../../../store/builder/store";

import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";

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

function use3DUndoHandler() {
    const { undoRedo3DStore, assetStore, productStore, eventStore, versionStore } = useSceneContext();
    const { deleteEvent, selectedProduct } = productStore();
    const { addEvent, removeEvent } = eventStore();
    const { updateAsset, removeAsset, addAsset } = assetStore();
    const { undo3D, peekUndo3D } = undoRedo3DStore();
    const { selectedVersion } = versionStore();
    const { userId, organization } = getUserData();
    const { projectId } = useParams();
    const { socket } = useSocketStore();

    const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
        upsertProductOrEventApi({
            productName: productName,
            productUuid: productUuid,
            projectId: projectId,
            eventDatas: eventData,
            versionId: selectedVersion?.versionId || "",
        });
    };

    const handleUndo = () => {
        const unDoData = peekUndo3D();
        if (!unDoData) return;

        if (unDoData.type === "Scene") {
            const { actions } = unDoData;

            actions.forEach((action) => {
                const { actionType } = action;

                if ("asset" in action) {
                    const asset = action.asset;

                    if (actionType === "Asset-Add") {
                        handleDelete(asset);
                    } else if (actionType === "Asset-Delete") {
                        handleAdd(asset);
                    } else if (actionType === "Asset-Update") {
                        handleUpdate(asset);
                    } else if (actionType === "Asset-Copied") {
                        handleCopy(asset);
                    } else if (actionType === "Asset-Duplicated") {
                        handleDuplicate(asset);
                    }
                } else if ("assets" in action) {
                    const assets = action.assets;

                    if (actionType === "Assets-Add") {
                        assets.forEach(handleDelete);
                    } else if (actionType === "Assets-Delete") {
                        assets.forEach(handleAdd);
                    } else if (actionType === "Assets-Update") {
                        assets.forEach(handleUpdate);
                    } else if (actionType === "Assets-Copied") {
                        assets.forEach(handleCopy);
                    } else if (actionType === "Assets-Duplicated") {
                        assets.forEach(handleDuplicate);
                    }
                }
            });
        } else if (unDoData.type === "UI") {
            // Handle UI actions if needed
        }

        undo3D();
    };

    const handleAdd = (asset: AssetData) => {
        switch (asset.type) {
            case "Asset":
                addAssetToBackend(asset.assetData);
                break;
            case "WallAsset":
                addWallAssetToBackend(asset.assetData);
                break;
        }
    };

    const handleDelete = (asset: AssetData) => {
        switch (asset.type) {
            case "Asset":
                deleteAssetToBackend(asset.assetData);
                break;
            case "WallAsset":
                deleteWallAssetToBackend(asset.assetData);
                break;
        }
    };

    const handleUpdate = (asset: AssetData) => {
        switch (asset.type) {
            case "Asset":
                updateAssetToBackend(asset.assetData.modelUuid, asset.assetData);
                break;
            case "WallAsset":
                updateWallAssetToBackend(asset.assetData.modelUuid, asset.assetData);
                break;
        }
    };

    const handleCopy = (asset: AssetData) => {
        switch (asset.type) {
            case "Asset":
                copyAssetToBackend(asset.assetData);
                break;
            case "WallAsset":
                copyWallAssetToBackend(asset.assetData);
                break;
        }
    };

    const handleDuplicate = (asset: AssetData) => {
        switch (asset.type) {
            case "Asset":
                duplicateAssetToBackend(asset.assetData);
                break;
            case "WallAsset":
                duplicateWallAssetToBackend(asset.assetData);
                break;
        }
    };

    const addAssetToBackend = (assetData: Asset) => {
        addAsset(assetData);
        if (projectId) {
            const data = {
                organization,
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                assetId: assetData.assetId,
                position: assetData.position,
                rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
                isLocked: false,
                isVisible: true,
                eventData: {},
                socketId: socket?.id,
                versionId: selectedVersion?.versionId || "",
                projectId,
                userId,
            };

            if (assetData.eventData) {
                data.eventData = assetData.eventData;
                addEvent(assetData.eventData as EventsSchema);
            }

            if (!socket?.connected) {
                // REST

                setAssetsApi({
                    modelUuid: assetData.modelUuid,
                    modelName: assetData.modelName,
                    assetId: assetData.assetId,
                    position: assetData.position,
                    rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
                    isLocked: false,
                    isVisible: true,
                    eventData: data.eventData,
                    versionId: selectedVersion?.versionId || "",
                    projectId: projectId,
                });
            } else {
                // SOCKET

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

    const deleteAssetToBackend = (assetData: Asset) => {
        if (!socket?.connected) {
            // REST

            deleteFloorAssetApi({
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                versionId: selectedVersion?.versionId || "",
                projectId: projectId || "",
            });
        } else {
            // SOCKET

            const data = {
                organization,
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                socketId: socket.id,
                userId,
                versionId: selectedVersion?.versionId || "",
                projectId,
            };

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

        removeEvent(assetData.modelUuid);
        const updatedEvents = deleteEvent(assetData.modelUuid);

        updatedEvents.forEach((event) => {
            updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
        });

        removeAsset(assetData.modelUuid);
    };

    const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
        updateAsset(modelUuid, updatedData);
        if (projectId) {
            const data = {
                organization,
                modelUuid: updatedData.modelUuid,
                modelName: updatedData.modelName,
                assetId: updatedData.assetId,
                position: updatedData.position,
                rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
                isLocked: false,
                isVisible: true,
                socketId: socket?.id,
                versionId: selectedVersion?.versionId || "",
                projectId,
                userId,
            };

            if (!socket?.connected) {
                // REST

                setAssetsApi({
                    modelUuid: updatedData.modelUuid,
                    modelName: updatedData.modelName,
                    assetId: updatedData.assetId,
                    position: updatedData.position,
                    rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
                    isLocked: false,
                    isVisible: true,
                    versionId: selectedVersion?.versionId || "",
                    projectId: projectId,
                });
            } else {
                // SOCKET

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

    const copyAssetToBackend = (assetData: Asset) => {
        if (!socket?.connected) {
            // REST

            deleteFloorAssetApi({
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                versionId: selectedVersion?.versionId || "",
                projectId: projectId || "",
            });
        } else {
            // SOCKET

            const data = {
                organization,
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                socketId: socket.id,
                userId,
                versionId: selectedVersion?.versionId || "",
                projectId,
            };

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

        removeEvent(assetData.modelUuid);
        const updatedEvents = deleteEvent(assetData.modelUuid);

        updatedEvents.forEach((event) => {
            updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
        });

        removeAsset(assetData.modelUuid);
    };

    const duplicateAssetToBackend = (assetData: Asset) => {
        if (!socket?.connected) {
            // REST

            deleteFloorAssetApi({
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                versionId: selectedVersion?.versionId || "",
                projectId: projectId || "",
            });
        } else {
            // SOCKET

            const data = {
                organization,
                modelUuid: assetData.modelUuid,
                modelName: assetData.modelName,
                socketId: socket.id,
                userId,
                versionId: selectedVersion?.versionId || "",
                projectId,
            };

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

        removeEvent(assetData.modelUuid);
        const updatedEvents = deleteEvent(assetData.modelUuid);

        updatedEvents.forEach((event) => {
            updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
        });

        removeAsset(assetData.modelUuid);
    };

    const addWallAssetToBackend = (assetData: WallAsset) => {};

    const deleteWallAssetToBackend = (assetData: WallAsset) => {};

    const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {};

    const copyWallAssetToBackend = (assetData: WallAsset) => {};

    const duplicateWallAssetToBackend = (assetData: WallAsset) => {};

    return { handleUndo };
}

export default use3DUndoHandler;
