import { useEffect, useState } from "react";
import { MathUtils } from "three";
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/products/UpsertProductOrEventApi";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";

function StorageMechanics() {
    const [activeOption, setActiveOption] = useState<"store" | "spawn">("store");
    const [currentCapacity, setCurrentCapacity] = useState("1");
    const [spawnedCount, setSpawnedCount] = useState("0");
    const [spawnedMaterial, setSpawnedMaterial] = useState("Default material");
    const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
    const { selectedEventData } = useSelectedEventData();
    const { productStore } = useSceneContext();
    const { getPointByUuid, updateAction, updateEvent, getEventByModelUuid, getActionByUuid, addAction, removeAction } = productStore();
    const { selectedProductStore } = useProductContext();
    const { selectedProduct } = selectedProductStore();
    const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { projectId } = useParams();

    useEffect(() => {
        if (selectedEventData && selectedEventData.data.type === "storageUnit") {
            const point = getPointByUuid(
                selectedProduct.productUuid,
                selectedEventData.data.modelUuid,
                selectedEventData.selectedPoint
            ) as StoragePointSchema | undefined;

            if (point?.actions?.length) {
                setSelectedPointData(point);
                const firstAction = point.actions[0];

                const eventData = getEventByModelUuid(
                    selectedProduct.productUuid,
                    selectedEventData.data.modelUuid
                ) as StorageEventSchema | undefined;

                setCurrentCapacity(eventData?.storageCapacity?.toString() || "1");
                setSpawnedCount(eventData?.storageCount?.toString() || "0");
                setSpawnedMaterial(eventData?.materialType?.toString() || "Default material");
                setSelectedAction(firstAction.actionUuid, firstAction.actionName);
                setActiveOption(firstAction.actionType === "retrieve" ? "spawn" : "store");
            }
        } else {
            clearSelectedAction();
        }
    }, [selectedEventData, selectedProduct]);

    useEffect(() => {
        if (selectedEventData && selectedEventData.data.type === "storageUnit" && selectedAction.actionId) {
            const point = getPointByUuid(
                selectedProduct.productUuid,
                selectedEventData.data.modelUuid,
                selectedEventData.selectedPoint
            ) as StoragePointSchema | undefined;

            const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || '';

            const newCurrentAction = getActionByUuid(selectedProduct.productUuid, actionUuid);

            if (newCurrentAction && (newCurrentAction.actionType === 'store' || newCurrentAction.actionType === 'retrieve')) {
                if (!selectedAction.actionId) {
                    setSelectedAction(newCurrentAction.actionUuid, newCurrentAction.actionName);
                }
                const uiOption = newCurrentAction.actionType === "retrieve" ? "spawn" : "store";
                setActiveOption(uiOption);
            } else {
                clearSelectedAction();
            }
        }
    }, [selectedAction, selectedProduct, selectedEventData]);

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

    const handleActionTypeChange = (option: string) => {
        if (!selectedAction.actionId || !selectedPointData) return;

        const internalOption = option === "spawn" ? "retrieve" : "store";

        const updatedAction = {
            actionType: internalOption as "store" | "retrieve"
        };

        const updatedActions = selectedPointData.actions.map(action =>
            action.actionUuid === selectedAction.actionId ? {
                ...action,
                actionType: updatedAction.actionType
            } : action
        );

        const updatedPoint = { ...selectedPointData, actions: updatedActions };

        const event = updateAction(
            selectedProduct.productUuid,
            selectedAction.actionId,
            updatedAction
        );

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productUuid,
                projectId || '',
                event
            );
        }

        setSelectedPointData(updatedPoint);
        setActiveOption(option as "store" | "spawn");
    };

    const handleCapacityChange = (value: string) => {
        if (!selectedEventData) return;

        const numericValue = parseInt(value);
        if (isNaN(numericValue)) return;

        const updatedEvent = {
            storageCapacity: numericValue
        } as StorageEventSchema;

        const currentCount = parseInt(spawnedCount);
        if (currentCount > numericValue) {
            updatedEvent.storageCount = numericValue;
            setSpawnedCount(numericValue.toString());
        }

        const event = updateEvent(
            selectedProduct.productUuid,
            selectedEventData.data.modelUuid,
            updatedEvent
        );

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productUuid,
                projectId || '',
                event
            );
        }

        setCurrentCapacity(value);
    };

    const handleSpawnCountChange = (value: string) => {
        if (!selectedEventData) return;

        const numericValue = parseInt(value);
        if (isNaN(numericValue)) return;

        const maxCapacity = parseInt(currentCapacity);
        if (numericValue > maxCapacity) return;

        const updatedEvent = {
            storageCount: numericValue
        } as StorageEventSchema;

        const event = updateEvent(
            selectedProduct.productUuid,
            selectedEventData.data.modelUuid,
            updatedEvent
        );

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productUuid,
                projectId || '',
                event
            );
        }

        setSpawnedCount(value);
    };

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

        const updatedEvent = {
            materialType: value
        } as StorageEventSchema;

        const event = updateEvent(
            selectedProduct.productUuid,
            selectedEventData.data.modelUuid,
            updatedEvent
        );

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productUuid,
                projectId || '',
                event
            );
        }

        setSpawnedMaterial(value);
    };

    const handleAddAction = () => {
        if (!selectedEventData || !selectedPointData) return;

        const newAction: StorageAction = {
            actionUuid: MathUtils.generateUUID(),
            actionName: `Action ${selectedPointData.actions.length + 1}`,
            actionType: "store",
            triggers: [],
        };

        const updatedActions = [...(selectedPointData.actions || []), newAction];
        const updatedPoint = { ...selectedPointData, actions: updatedActions };

        const event = addAction(
            selectedProduct.productUuid,
            selectedEventData.data.modelUuid,
            selectedEventData.selectedPoint,
            newAction
        );

        if (event) {
            updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
        }

        setSelectedPointData(updatedPoint);
        setSelectedAction(newAction.actionUuid, newAction.actionName);
    };

    const handleDeleteAction = (actionUuid: string) => {
        if (!selectedPointData || !actionUuid) return;

        const updatedActions = selectedPointData.actions.filter(action => action.actionUuid !== actionUuid);
        const updatedPoint = { ...selectedPointData, actions: updatedActions };

        const event = removeAction(
            selectedProduct.productUuid,
            actionUuid
        );

        if (event) {
            updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
        }

        setSelectedPointData(updatedPoint);

        const index = selectedPointData.actions.findIndex((a) => a.actionUuid === selectedAction.actionId);
        const nextAction = updatedPoint.actions[index] || updatedPoint.actions[index - 1];
        if (nextAction) {
            setSelectedAction(nextAction.actionUuid, nextAction.actionName);
        } else {
            clearSelectedAction();
        }
    };

    return (
        <>
            {selectedEventData && selectedEventData.data.type === "storageUnit" && (
                <>
                    <section>
                        <StorageAction
                            maxCapacity={currentCapacity}
                            spawnedCount={spawnedCount}
                            maxCapacityDefault="0"
                            spawnedCountCefault="0"
                            min={0}
                            currentMaterialType={spawnedMaterial}
                            handleCapacityChange={handleCapacityChange}
                            handleSpawnCountChange={handleSpawnCountChange}
                            handleMaterialTypeChange={handleMaterialTypeChange}
                        />
                    </section>
                    <section>
                        <ActionsList
                            selectedPointData={selectedPointData}
                            multipleAction={true}
                            handleAddAction={handleAddAction}
                            handleDeleteAction={handleDeleteAction}
                        />

                        {selectedAction.actionId && (
                            <div className="selected-actions-details">
                                <div className="selected-actions-header">
                                    <RenameInput
                                        value={selectedAction.actionName || ""}
                                        canEdit={false}
                                    />
                                </div>
                                <div className="selected-actions-list">
                                    <LabledDropdown
                                        label="Action Type"
                                        defaultOption={activeOption}
                                        options={["store", "spawn"]}
                                        onSelect={handleActionTypeChange}
                                        disabled={false}
                                    />
                                </div>
                                <div className="tirgger">
                                    <Trigger selectedPointData={selectedPointData as any} type={'StorageUnit'} />
                                </div>
                            </div>
                        )}
                    </section>
                </>
            )}
        </>
    );
}

export default StorageMechanics;