import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useSceneContext } from "../../../sceneContext";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useSocketStore } from "../../../../../store/builder/store";

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

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

function use3DRedoHandler() {
    const { undoRedo3DStore, assetStore, productStore, eventStore } = useSceneContext();
    const { deleteEvent } = productStore();
    const { addEvent, removeEvent } = eventStore();
    const { updateAsset, removeAsset, addAsset } = assetStore();
    const { redo3D, peekRedo3D } = undoRedo3DStore();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { selectedProductStore } = useProductContext();
    const { selectedProduct } = selectedProductStore();
    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 handleRedo = () => {
        const redoData = peekRedo3D();
        if (!redoData) return;

        if (redoData.type === 'Scene') {
            const { actions } = redoData;

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

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

                    if (actionType === 'Asset-Add') {
                        handleAdd(asset);
                    } else if (actionType === 'Asset-Delete') {
                        handleDelete(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(handleAdd);
                    } else if (actionType === 'Assets-Delete') {
                        assets.forEach(handleDelete);
                    } 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 (redoData.type === 'UI') {
            // Handle UI actions if needed
        }

        redo3D();
    };


    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) => {
        if (!asset.newData) return;
        switch (asset.type) {
            case 'Asset': updateAssetToBackend(asset.newData.modelUuid, asset.newData); break;
            case 'WallAsset': updateWallAssetToBackend(asset.newData.modelUuid, asset.newData); 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);
            }

            // API

            // setAssetsApi(data);

            //SOCKET

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

    const deleteAssetToBackend = (assetData: Asset) => {
        //REST

        // const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);

        //SOCKET 

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

        const response = 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
            );
        })

        if (response) {

            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
            };

            // API

            // setAssetsApi(data);

            //SOCKET

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

    const copyAssetToBackend = (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);
            }

            // API

            // setAssetsApi(data);

            //SOCKET

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

    const duplicateAssetToBackend = (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);
            }

            // API

            // setAssetsApi(data);

            //SOCKET

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

    const addWallAssetToBackend = (assetData: WallAsset) => {

    }

    const deleteWallAssetToBackend = (assetData: WallAsset) => {

    }

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

    }

    const copyWallAssetToBackend = (assetData: WallAsset) => {

    }

    const duplicateWallAssetToBackend = (assetData: WallAsset) => {

    }

    return { handleRedo };
}

export default use3DRedoHandler;
