import React, { useRef, useState, useMemo, useEffect } from "react";
import {
    AddIcon,
    InfoIcon,
    RemoveIcon,
    ResizeHeightIcon,
} from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
import { handleResize } from "../../../../functions/handleResizePannel";
import {
    useFloorItems,
    useSelectedActionSphere,
    useSelectedPath,
    useSimulationStates,
    useSocketStore,
} from "../../../../store/store";
import * as THREE from "three";
import * as Types from "../../../../types/world/worldTypes";
import InputToggle from "../../../ui/inputs/InputToggle";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";

const ConveyorMechanics: React.FC = () => {
    const { selectedActionSphere } = useSelectedActionSphere();
    const { selectedPath, setSelectedPath } = useSelectedPath();
    const { simulationStates, setSimulationStates } = useSimulationStates();
    const { floorItems, setFloorItems } = useFloorItems();
    const { socket } = useSocketStore();

    const actionsContainerRef = useRef<HTMLDivElement>(null);
    const triggersContainerRef = useRef<HTMLDivElement>(null);

    const selectedPoint = useMemo(() => {
        if (!selectedActionSphere) return null;
        return simulationStates
            .filter(
                (path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
            )
            .flatMap((path) => path.points)
            .find((point) => point.uuid === selectedActionSphere.points.uuid);
    }, [selectedActionSphere, simulationStates]);

    const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
        if (!updatedPath) return;
        const email = localStorage.getItem("email");
        const organization = email ? email.split("@")[1].split(".")[0] : "";

        // await setEventApi(
        //   organization,
        //   updatedPath.modeluuid,
        //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
        // );

        const data = {
            organization: organization,
            modeluuid: updatedPath.modeluuid,
            eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
        }

        socket.emit('v2:model-asset:updateEventData', data);

    }

    const handleAddAction = () => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) => {
            if (path.type === "Conveyor") {
                return {
                    ...path,
                    points: path.points.map((point) => {
                        if (point.uuid === selectedActionSphere.points.uuid) {
                            const actionIndex = point.actions.length;
                            const newAction = {
                                uuid: THREE.MathUtils.generateUUID(),
                                name: `Action ${actionIndex + 1}`,
                                type: "Inherit",
                                material: "Inherit",
                                delay: "Inherit",
                                spawnInterval: "Inherit",
                                isUsed: false,
                            };

                            return { ...point, actions: [...point.actions, newAction] };
                        }
                        return point;
                    }),
                };
            }
            return path;
        });

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleDeleteAction = (uuid: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.filter(
                                    (action) => action.uuid !== uuid
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleActionSelect = (uuid: string, actionType: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.map((action) =>
                                    action.uuid === uuid
                                        ? {
                                            ...action,
                                            type: actionType,
                                            material:
                                                actionType === "Spawn" || actionType === "Swap"
                                                    ? "Inherit"
                                                    : action.material,
                                            delay:
                                                actionType === "Delay" ? "Inherit" : action.delay,
                                            spawnInterval:
                                                actionType === "Spawn"
                                                    ? "Inherit"
                                                    : action.spawnInterval,
                                        }
                                        : action
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Update the selected item to reflect changes
        if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
            const updatedAction = updatedPaths
                .filter(
                    (path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
                )
                .flatMap((path) => path.points)
                .find((p) => p.uuid === selectedActionSphere.points.uuid)
                ?.actions.find((a) => a.uuid === uuid);

            if (updatedAction) {
                setSelectedItem({
                    type: "action",
                    item: updatedAction,
                });
            }
        }
    };

    // Modified handleMaterialSelect to ensure it only applies to relevant action types
    const handleMaterialSelect = (uuid: string, material: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.map((action) =>
                                    action.uuid === uuid &&
                                        (action.type === "Spawn" || action.type === "Swap")
                                        ? { ...action, material }
                                        : action
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Update selected item if it's the current action
        if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
            setSelectedItem({
                ...selectedItem,
                item: {
                    ...selectedItem.item,
                    material,
                },
            });
        }
    };

    const handleDelayChange = (uuid: string, delay: number | string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.map((action) =>
                                    action.uuid === uuid ? { ...action, delay } : action
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleSpawnIntervalChange = (
        uuid: string,
        spawnInterval: number | string
    ) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.map((action) =>
                                    action.uuid === uuid
                                        ? { ...action, spawnInterval }
                                        : action
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleSpeedChange = (speed: number | string) => {
        if (!selectedPath) return;

        const updatedPaths = simulationStates.map((path) =>
            path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.modeluuid === selectedPath.path.modeluuid
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
        setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
    };

    const handleAddTrigger = () => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) => {
                        if (point.uuid === selectedActionSphere.points.uuid) {
                            const triggerIndex = point.triggers.length;
                            const newTrigger = {
                                uuid: THREE.MathUtils.generateUUID(),
                                name: `Trigger ${triggerIndex + 1}`,
                                type: "",
                                bufferTime: 0,
                                isUsed: false,
                            };

                            return { ...point, triggers: [...point.triggers, newTrigger] };
                        }
                        return point;
                    }),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleDeleteTrigger = (uuid: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                triggers: point.triggers.filter(
                                    (trigger) => trigger.uuid !== uuid
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);
    };

    const handleTriggerSelect = (uuid: string, triggerType: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                triggers: point.triggers.map((trigger) =>
                                    trigger.uuid === uuid
                                        ? { ...trigger, type: triggerType }
                                        : trigger
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Ensure the selectedItem is updated immediately
        const updatedTrigger = updatedPaths
            .flatMap((path) => (path.type === "Conveyor" ? path.points : []))
            .flatMap((point) => point.triggers)
            .find((trigger) => trigger.uuid === uuid);

        if (updatedTrigger) {
            setSelectedItem({ type: "trigger", item: updatedTrigger });
        }
    };

    // Update the toggle handlers to immediately update the selected item
    const handleActionToggle = (uuid: string) => {
        if (!selectedActionSphere) return;
        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                actions: point.actions.map((action) => ({
                                    ...action,
                                    isUsed: action.uuid === uuid ? !action.isUsed : false,
                                })),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Immediately update the selected item if it's the one being toggled
        if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
            setSelectedItem({
                ...selectedItem,
                item: {
                    ...selectedItem.item,
                    isUsed: !selectedItem.item.isUsed,
                },
            });
        }
    };

    // Do the same for trigger toggle
    const handleTriggerToggle = (uuid: string) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                triggers: point.triggers.map((trigger) => ({
                                    ...trigger,
                                    isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
                                })),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Immediately update the selected item if it's the one being toggled
        if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
            setSelectedItem({
                ...selectedItem,
                item: {
                    ...selectedItem.item,
                    isUsed: !selectedItem.item.isUsed,
                },
            });
        }
    };

    const handleTriggerBufferTimeChange = (uuid: string, bufferTime: number) => {
        if (!selectedActionSphere) return;

        const updatedPaths = simulationStates.map((path) =>
            path.type === "Conveyor"
                ? {
                    ...path,
                    points: path.points.map((point) =>
                        point.uuid === selectedActionSphere.points.uuid
                            ? {
                                ...point,
                                triggers: point.triggers.map((trigger) =>
                                    trigger.uuid === uuid
                                        ? { ...trigger, bufferTime }
                                        : trigger
                                ),
                            }
                            : point
                    ),
                }
                : path
        );

        const updatedPath = updatedPaths.find(
            (path): path is Types.ConveyorEventsSchema =>
                path.type === "Conveyor" &&
                path.points.some(
                    (point) => point.uuid === selectedActionSphere.points.uuid
                )
        );
        updateBackend(updatedPath);

        setSimulationStates(updatedPaths);

        // Immediately update selectedItem if it's the currently selected trigger
        if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
            setSelectedItem({
                ...selectedItem,
                item: {
                    ...selectedItem.item,
                    bufferTime,
                },
            });
        }
    };

    const [selectedItem, setSelectedItem] = useState<{
        type: "action" | "trigger";
        item: any;
    } | null>(null);

    useEffect(() => {
        setSelectedItem(null);
    }, [selectedActionSphere]);

    return (
        <div className="machine-mechanics-container">
            {!selectedPath && (
                <div className="machine-mechanics-header">
                    {selectedActionSphere?.path?.modelName || "point name not found"}
                </div>
            )}

            {selectedPath && (
                <div className="machine-mechanics-header">
                    {selectedPath.path.modelName || "path name not found"}
                </div>
            )}

            <div className="machine-mechanics-content-container">
                {!selectedPath && (
                    <>
                        <div className="actions">
                            <div className="header">
                                <div className="header-value">Actions</div>
                                <div className="add-button" onClick={handleAddAction}>
                                    <AddIcon /> Add
                                </div>
                            </div>
                            <div
                                className="lists-main-container"
                                ref={actionsContainerRef}
                                style={{ height: "120px" }}
                            >
                                <div className="list-container">
                                    {selectedPoint?.actions.map((action) => (
                                        <div
                                            key={action.uuid}
                                            className={`list-item ${selectedItem?.type === "action" &&
                                                selectedItem.item?.uuid === action.uuid
                                                ? "active"
                                                : ""
                                                }`}
                                        >
                                            <div
                                                className="value"
                                                onClick={() =>
                                                    setSelectedItem({ type: "action", item: action })
                                                }
                                            >
                                                <input type="radio" name="action" id="action" defaultChecked={action.isUsed} />
                                                <RenameInput value={action.name} />
                                            </div>
                                            <div
                                                className="remove-button"
                                                onClick={() => handleDeleteAction(action.uuid)}
                                            >
                                                <RemoveIcon />
                                            </div>
                                        </div>
                                    ))}
                                </div>
                                <div
                                    className="resize-icon"
                                    id="action-resize"
                                    onMouseDown={(e) => handleResize(e, actionsContainerRef)}
                                >
                                    <ResizeHeightIcon />
                                </div>
                            </div>
                        </div>
                        <div className="triggers">
                            <div className="header">
                                <div className="header-value">Triggers</div>
                                <div className="add-button" onClick={handleAddTrigger}>
                                    <AddIcon /> Add
                                </div>
                            </div>
                            <div
                                className="lists-main-container"
                                ref={triggersContainerRef}
                                style={{ height: "120px" }}
                            >
                                <div className="list-container">
                                    {selectedPoint?.triggers.map((trigger) => (
                                        <div
                                            key={trigger.uuid}
                                            className={`list-item ${selectedItem?.type === "trigger" &&
                                                selectedItem.item?.uuid === trigger.uuid
                                                ? "active"
                                                : ""
                                                }`}
                                        >
                                            <div
                                                className="value"
                                                onClick={() =>
                                                    setSelectedItem({ type: "trigger", item: trigger })
                                                }
                                            >
                                                <input type="radio" name="trigger" id="trigger" defaultChecked={trigger.isUsed} />
                                                <RenameInput value={trigger.name} />
                                            </div>
                                            <div
                                                className="remove-button"
                                                onClick={() => handleDeleteTrigger(trigger.uuid)}
                                            >
                                                <RemoveIcon />
                                            </div>
                                        </div>
                                    ))}
                                </div>
                                <div
                                    className="resize-icon"
                                    id="trigger-resize"
                                    onMouseDown={(e) => handleResize(e, triggersContainerRef)}
                                >
                                    <ResizeHeightIcon />
                                </div>
                            </div>
                        </div>
                    </>
                )}

                <div className="selected-properties-container">
                    {selectedItem && (
                        <>
                            <div className="properties-header">{selectedItem.item.name}</div>

                            {selectedItem.type === "action" && (
                                <>
                                    <InputToggle
                                        inputKey="enableAction"
                                        label="Enable Action"
                                        value={selectedItem.item.isUsed}
                                        onClick={() => handleActionToggle(selectedItem.item.uuid)}
                                    />
                                    <LabledDropdown
                                        defaultOption={selectedItem.item.type}
                                        options={["Inherit", "Spawn", "Swap", "Despawn", "Delay"]}
                                        onSelect={(option) =>
                                            handleActionSelect(selectedItem.item.uuid, option)
                                        }
                                    />

                                    {/* Only show material dropdown for Spawn/Swap actions */}
                                    {(selectedItem.item.type === "Spawn" ||
                                        selectedItem.item.type === "Swap") && (
                                            <LabledDropdown
                                                label={
                                                    selectedItem.item.type === "Spawn"
                                                        ? "Spawn Material"
                                                        : "Swap Material"
                                                }
                                                defaultOption={selectedItem.item.material}
                                                options={["Inherit", "Crate", "Box"]}
                                                onSelect={(option) =>
                                                    handleMaterialSelect(selectedItem.item.uuid, option)
                                                }
                                            />
                                        )}

                                    {/* Only show delay input for Delay actions */}
                                    {selectedItem.item.type === "Delay" && (
                                        <InputWithDropDown
                                            label="Delay Time"
                                            value={
                                                selectedItem.item.delay === "Inherit"
                                                    ? undefined
                                                    : selectedItem.item.delay
                                            }
                                            onChange={(value) => {
                                                const numValue = parseInt(value);
                                                handleDelayChange(
                                                    selectedItem.item.uuid,
                                                    !value ? "Inherit" : numValue
                                                );
                                            }}
                                        />
                                    )}

                                    {/* Only show spawn interval for Spawn actions */}
                                    {selectedItem.item.type === "Spawn" && (
                                        <InputWithDropDown
                                            label="Spawn Interval"
                                            min={0}
                                            defaultValue={
                                                selectedItem.item.spawnInterval === "Inherit"
                                                    ? ""
                                                    : selectedItem.item.spawnInterval.toString()
                                            }
                                            value={
                                                selectedItem.item.spawnInterval === "Inherit"
                                                    ? ""
                                                    : selectedItem.item.spawnInterval.toString()
                                            }
                                            onChange={(value) => {
                                                handleSpawnIntervalChange(
                                                    selectedItem.item.uuid,
                                                    value === "" ? "Inherit" : parseInt(value)
                                                );
                                            }}
                                        />
                                    )}
                                </>
                            )}

                            {selectedItem.type === "trigger" && (
                                <>
                                    <InputToggle
                                        inputKey="enableTrigger"
                                        label="Enable Trigger"
                                        value={selectedItem.item.isUsed}
                                        onClick={() => handleTriggerToggle(selectedItem.item.uuid)}
                                    />

                                    <LabledDropdown
                                        defaultOption={
                                            selectedItem.item.type || "Select Trigger Type"
                                        }
                                        options={["On-Hit", "Buffer"]}
                                        onSelect={(option) =>
                                            handleTriggerSelect(selectedItem.item.uuid, option)
                                        }
                                    />

                                    {selectedItem.item.type === "Buffer" && (
                                        <InputWithDropDown
                                            label="Buffer Time"
                                            value={selectedItem.item.bufferTime.toString()}
                                            onChange={(value) => {
                                                handleTriggerBufferTimeChange(
                                                    selectedItem.item.uuid,
                                                    parseInt(value)
                                                );
                                            }}
                                        />
                                    )}
                                </>
                            )}
                        </>
                    )}

                    {selectedPath && !selectedItem && (
                        <div
                            key={selectedPath?.path.modeluuid || "none"}
                            className="speed-control"
                        >
                            <InputWithDropDown
                                label="Conveyor Speed"
                                min={0}
                                value={
                                    selectedPath.path.speed === "Inherit"
                                        ? ""
                                        : selectedPath.path.speed.toString()
                                }
                                onChange={(value) =>
                                    handleSpeedChange(value === "" ? "Inherit" : parseInt(value))
                                }
                            />
                        </div>
                    )}
                </div>
                {!selectedPath && (
                    <div className="footer">
                        <InfoIcon />
                        Configure the point's action and trigger properties.
                    </div>
                )}
                {selectedPath && (
                    <div className="footer">
                        <InfoIcon />
                        Configure the path properties.
                    </div>
                )}
            </div>
        </div>
    );
};

export default ConveyorMechanics;
