import { useEffect, useMemo, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import StorageAction from "../actions/StorageAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/UpsertProductOrEventApi";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { useStorageUnitStore } from "../../../../../../store/simulation/useStorageUnitStore";
import { useSelectedAction, useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import * as THREE from 'three';

function StorageMechanics() {
    const [activeOption, setActiveOption] = useState<"default" | "store" | "spawn">("default");
    const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
    const { selectedEventData } = useSelectedEventData();
    const { getPointByUuid, updateAction } = useProductStore();
    const { selectedProduct } = useSelectedProduct();
    const { setSelectedAction, clearSelectedAction } = useSelectedAction();
    const { setCurrentMaterials, clearCurrentMaterials, updateCurrentLoad, getStorageUnitById } = useStorageUnitStore();

    const email = localStorage.getItem('email')
    const organization = (email!.split("@")[1]).split(".")[0];

    const updateSelectedPointData = () => {
        if (selectedEventData && selectedProduct) {
            const point = getPointByUuid(
                selectedProduct.productId,
                selectedEventData?.data.modelUuid,
                selectedEventData?.selectedPoint
            ) as StoragePointSchema | undefined;
            if (point && "action" in point) {
                setSelectedPointData(point);
                const uiOption = point.action.actionType === "retrieve" ? "spawn" : point.action.actionType;
                setActiveOption(uiOption as "store" | "spawn");
                setSelectedAction(point.action.actionUuid, point.action.actionName);
            }
        }
    };

    useEffect(() => {
        if (selectedEventData) {
            const point = getPointByUuid(
                selectedProduct.productId,
                selectedEventData?.data.modelUuid,
                selectedEventData?.selectedPoint
            ) as StoragePointSchema | undefined;
            if (point && "action" in point) {
                setSelectedPointData(point);
                const uiOption = point.action.actionType === "retrieve" ? "spawn" : point.action.actionType;
                setActiveOption(uiOption as "store" | "spawn");
                setSelectedAction(point.action.actionUuid, point.action.actionName);
            }
        } else {
            clearSelectedAction();
        }
    }, [selectedProduct, selectedEventData]);

    const updateBackend = (
        productName: string,
        productId: string,
        organization: string,
        eventData: EventsSchema
    ) => {
        upsertProductOrEventApi({
            productName: productName,
            productId: productId,
            organization: organization,
            eventDatas: eventData
        })
    }

    const handleActionTypeChange = (option: string) => {
        if (!selectedEventData || !selectedPointData) return;
        const internalOption = actionTypeMap[option as keyof typeof actionTypeMap] as "store" | "retrieve";

        setActiveOption(option as "store" | "spawn");

        const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, {
            actionType: internalOption,
        });

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                event
            );
            updateSelectedPointData();
        }

        if (option === "spawn") {
            const storageUnit = getStorageUnitById(selectedEventData.data.modelUuid);
            if (storageUnit) {
                const materialType = selectedPointData.action.materialType || "Default material";
                const materials = Array.from({ length: selectedPointData.action.storageCapacity }, () =>
                    createNewMaterial(materialType)
                ).filter(Boolean) as { materialType: string; materialId: string }[];

                setCurrentMaterials(selectedEventData.data.modelUuid, materials);
                updateCurrentLoad(selectedEventData.data.modelUuid, selectedPointData.action.storageCapacity);
            }
        } else {
            clearCurrentMaterials(selectedEventData.data.modelUuid);
            updateCurrentLoad(selectedEventData.data.modelUuid, 0);
        }
    };

    const handleRenameAction = (newName: string) => {
        if (!selectedPointData) return;
        const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionName: newName });

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                event
            );
            updateSelectedPointData();
        }
    };

    const handleCapacityChange = (value: string) => {
        if (!selectedEventData || !selectedPointData) return;
        const newCapacity = parseInt(value);

        const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, {
            storageCapacity: newCapacity,
        });

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                event
            );
            updateSelectedPointData();

            if (activeOption === "spawn") {
                const storageUnit = getStorageUnitById(selectedEventData.data.modelUuid);
                if (storageUnit) {
                    const materialType = selectedPointData.action.materialType || "Default material";
                    const materials = Array.from({ length: selectedPointData.action.storageCapacity }, () =>
                        createNewMaterial(materialType)
                    ).filter(Boolean) as { materialType: string; materialId: string }[];

                    setCurrentMaterials(selectedEventData.data.modelUuid, materials);
                    updateCurrentLoad(selectedEventData.data.modelUuid, selectedPointData.action.storageCapacity);
                }
            } else {
                updateCurrentLoad(selectedEventData.data.modelUuid, 0);
            }
        }
    };

    const createNewMaterial = (materialType: string): { materialType: string; materialId: string } | null => {
        if (!selectedEventData || !selectedPointData) return null;
        const materialId = THREE.MathUtils.generateUUID();
        return {
            materialType,
            materialId
        };
    };

    const handleMaterialTypeChange = (value: string) => {
        if (!selectedEventData || !selectedPointData) return;

        const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, {
            materialType: value,
        });

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                event
            );
            updateSelectedPointData();

            if (activeOption === "spawn") {
                const storageUnit = getStorageUnitById(selectedEventData.data.modelUuid);
                if (storageUnit) {
                    const materials = Array.from({ length: storageUnit.currentMaterials.length }, () =>
                        createNewMaterial(value)
                    ).filter(Boolean) as { materialType: string; materialId: string }[];

                    setCurrentMaterials(selectedEventData.data.modelUuid, materials);
                }
            }
        }
    };

    const currentActionName = useMemo(() =>
        selectedPointData ? selectedPointData.action.actionName : "Action Name",
        [selectedPointData]
    );

    const currentCapacity = useMemo(() =>
        selectedPointData ? selectedPointData.action.storageCapacity.toString() : "0",
        [selectedPointData]
    );

    const currentMaterialType = useMemo(() =>
        selectedPointData?.action.materialType || "Default material",
        [selectedPointData]
    );

    const availableActions = {
        defaultOption: "store",
        options: ["store", "spawn"],
    };

    const actionTypeMap = {
        spawn: "retrieve",
        store: "store"
    };

    return (
        <>
            {selectedEventData && (
                <section>
                    <ActionsList
                        selectedPointData={selectedPointData}
                    />
                    <div className="selected-actions-details">
                        <div className="selected-actions-header">
                            <RenameInput
                                value={currentActionName}
                                onRename={handleRenameAction}
                            />
                        </div>
                        <div className="selected-actions-list">
                            <LabledDropdown
                                defaultOption={activeOption}
                                options={availableActions.options}
                                onSelect={handleActionTypeChange}
                            />
                            <StorageAction
                                type={activeOption}
                                value={currentCapacity}
                                defaultValue="0"
                                min={0}
                                currentMaterialType={currentMaterialType}
                                handleCapacityChange={handleCapacityChange}
                                handleMaterialTypeChange={handleMaterialTypeChange}
                            />
                        </div>
                    </div>
                    <div className="tirgger">
                        <Trigger selectedPointData={selectedPointData as any} type={'StorageUnit'} />
                    </div>
                </section>
            )}
        </>
    );
}

export default StorageMechanics;