import React, { useEffect, useMemo, useRef, useState } from "react";
import * as THREE from "three";
import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../../../functions/handleResizePannel";
import { useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
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";

type TriggerProps = {
    selectedPointData?: PointsScheme | undefined;
    type?: "Conveyor" | "Vehicle" | "RoboticArm" | "Machine" | "StorageUnit" | "Human";
};

const Trigger = ({ selectedPointData, type }: TriggerProps) => {
    const [currentAction, setCurrentAction] = useState<string | undefined>();
    const { selectedProductStore } = useProductContext();
    const { selectedProduct } = selectedProductStore();
    const { productStore } = useSceneContext();
    const { getActionByUuid, getEventByModelUuid, getPointByUuid, getTriggerByUuid, addTrigger, removeTrigger, updateTrigger, renameTrigger, getProductById, } = productStore();
    const [triggers, setTriggers] = useState<TriggerSchema[]>([]);
    const [selectedTrigger, setSelectedTrigger] = useState<TriggerSchema | undefined>();
    const [activeOption, setActiveOption] = useState<"onComplete" | "onStart" | "onStop" | "delay" | "onError">("onComplete");
    const triggersContainerRef = useRef<HTMLDivElement>(null);
    const { selectedAction } = useSelectedAction();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { projectId } = useParams();

    useEffect(() => {
        if (!selectedPointData || !selectedProduct) return;

        let actionUuid: string | undefined;

        if (type === "Conveyor" || type === "Vehicle" || type === "Machine" || type === "StorageUnit") {
            actionUuid = (selectedPointData as | ConveyorPointSchema | VehiclePointSchema | MachinePointSchema | StoragePointSchema).action?.actionUuid;
        } else if ((type === "RoboticArm" || type === "Human") && selectedAction.actionId) {
            actionUuid = selectedAction.actionId;
        }

        setCurrentAction(actionUuid);
    }, [selectedPointData, selectedProduct, type, selectedAction]);

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

    useEffect(() => {
        if (!currentAction || !selectedProduct) return;
        const action = getActionByUuid(selectedProduct.productUuid, currentAction);
        const actionTriggers = action?.triggers || [];
        setTriggers(actionTriggers);
        if (actionTriggers.length === 0) {
            setSelectedTrigger(undefined);
        }
        setSelectedTrigger(actionTriggers[0]);
    }, [currentAction, selectedProduct, selectedTrigger, selectedPointData]);

    const triggeredModel = useMemo(() => {
        if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredModel?.modelUuid)
            return undefined;
        return getEventByModelUuid(
            selectedProduct.productUuid,
            selectedTrigger.triggeredAsset.triggeredModel.modelUuid
        );
    }, [selectedProduct, selectedTrigger]);

    const triggeredPoint = useMemo(() => {
        if (!selectedProduct || !triggeredModel || !selectedTrigger?.triggeredAsset?.triggeredPoint?.pointUuid)
            return undefined;
        return getPointByUuid(
            selectedProduct.productUuid,
            triggeredModel.modelUuid,
            selectedTrigger.triggeredAsset.triggeredPoint.pointUuid
        );
    }, [selectedProduct, triggeredModel, selectedTrigger]);

    const triggeredAction = useMemo(() => {
        if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredAction?.actionUuid)
            return undefined;
        return getActionByUuid(
            selectedProduct.productUuid,
            selectedTrigger.triggeredAsset.triggeredAction.actionUuid
        );
    }, [selectedProduct, selectedTrigger]);

    const modelOptions = getProductById(selectedProduct.productUuid)?.eventDatas || [];

    const pointOptions: PointsScheme[] = useMemo(() => {
        if (!triggeredModel) return [];

        const model = modelOptions.find((m) => m.modelUuid === triggeredModel.modelUuid);
        if (!model) return [];

        if ("points" in model) {
            return (model).points;
        } else if ("point" in model) {
            return [model.point];
        }
        return [];
    }, [triggeredModel, modelOptions]);

    const actionOptions: any = useMemo(() => {
        if (!triggeredPoint) return [];
        const point = pointOptions.find((p) => p.uuid === triggeredPoint.uuid);
        if (!point) return [];

        if ("action" in point) {
            const typedPoint = point;
            return typedPoint.action ? [typedPoint.action] : [];
        } else if ("actions" in point) {
            const typedPoint = point;
            return typedPoint.actions;
        }
        return [];
    }, [triggeredPoint, pointOptions]);

    const handleModelSelect = (option: string, triggerUuid: string) => {
        if (!selectedProduct) return;

        const selectedModel = modelOptions.find((m) => m.modelName === option);
        if (!selectedModel) return;

        const event = updateTrigger(selectedProduct.productUuid, triggerUuid, {
            triggeredAsset: {
                triggeredModel: {
                    modelName: selectedModel.modelName,
                    modelUuid: selectedModel.modelUuid,
                },
                triggeredPoint: null,
                triggeredAction: null,
            },
        });

        if (event) {
            const updatedTrigger = getTriggerByUuid(
                selectedProduct.productUuid,
                triggerUuid
            );
            setSelectedTrigger(updatedTrigger);

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

    const handlePointSelect = (option: string, triggerUuid: string) => {
        if (!selectedProduct || !selectedTrigger) return;

        const pointUuid = pointOptions.find((p) => `Point ${p.uuid.slice(0, 4)}` === option)?.uuid;
        if (!pointUuid) return;

        if (selectedTrigger.triggeredAsset?.triggeredModel) {
            const event = updateTrigger(selectedProduct.productUuid, triggerUuid, {
                triggeredAsset: {
                    ...selectedTrigger.triggeredAsset,
                    triggeredPoint: {
                        pointName: option,
                        pointUuid: pointUuid,
                    },
                    triggeredAction: null,
                },
            });

            if (event) {
                const updatedTrigger = getTriggerByUuid(
                    selectedProduct.productUuid,
                    triggerUuid
                );
                setSelectedTrigger(updatedTrigger);

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

    const handleActionSelect = (option: string, triggerUuid: string) => {
        if (!selectedProduct || !selectedTrigger) return;

        const selectedAction = actionOptions.find((a: any) => a.actionName === option);

        if (!selectedAction) return;

        if (selectedTrigger.triggeredAsset?.triggeredPoint) {
            const event = updateTrigger(selectedProduct.productUuid, triggerUuid, {
                triggeredAsset: {
                    ...selectedTrigger.triggeredAsset,
                    triggeredAction: {
                        actionName: option,
                        actionUuid: selectedAction.actionUuid,
                    },
                },
            });

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

    const handleAddTrigger = () => {
        if (!selectedProduct || !currentAction) return;

        const newTrigger: TriggerSchema = {
            triggerUuid: THREE.MathUtils.generateUUID(),
            triggerName: `New Trigger ${triggers.length + 1}`,
            triggerType: activeOption,
            delay: 0,
            triggeredAsset: null,
        };

        const event = addTrigger(
            selectedProduct.productUuid,
            currentAction,
            newTrigger
        );

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

        const updatedAction = getActionByUuid(
            selectedProduct.productUuid,
            currentAction
        );
        const updatedTriggers = updatedAction?.triggers || [];

        setTriggers(updatedTriggers);
        setSelectedTrigger(newTrigger);
    };

    const handleRemoveTrigger = (triggerUuid: string) => {
        if (!selectedProduct || !currentAction) return;

        const event = removeTrigger(selectedProduct.productUuid, triggerUuid);

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

        const index = triggers.findIndex((t) => t.triggerUuid === triggerUuid);
        const newTriggers = triggers.filter((t) => t.triggerUuid !== triggerUuid);
        setTriggers(newTriggers);

        if (selectedTrigger?.triggerUuid === triggerUuid) {
            const nextTrigger = newTriggers[index] || newTriggers[index - 1];
            setSelectedTrigger(nextTrigger);
        }
    };

    const handleTriggerRename = (triggerUuid: string, newName: string) => {
        if (!selectedProduct) return;
        const event = renameTrigger(
            selectedProduct.productUuid,
            triggerUuid,
            newName
        );

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

    const handleTriggerTypeChange = (option: string) => {
        if (!selectedTrigger || !selectedProduct) return;

        const validTypes: Array<TriggerSchema["triggerType"]> = ["onComplete", "onStart", "onStop", "delay", "onError",];
        if (!validTypes.includes(option as TriggerSchema["triggerType"])) return;

        setActiveOption(option as TriggerSchema["triggerType"]);
        const event = updateTrigger(
            selectedProduct.productUuid,
            selectedTrigger.triggerUuid,
            {
                triggerType: option as TriggerSchema["triggerType"],
            }
        );

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

    return (
        <div className="trigger-wrapper">
            <div className="header">
                <div className="title">Trigger</div>
                <button
                    id="add-trigger-button"
                    className="add-button"
                    onClick={handleAddTrigger}
                    style={{ cursor: "pointer" }}
                    disabled={!currentAction}
                >
                    <AddIcon /> Add
                </button>
            </div>
            <div className="trigger-list">
                <div
                    className="lists-main-container"
                    ref={triggersContainerRef}
                    style={{ height: "120px" }}
                >
                    <div className="list-container">
                        {triggers.map((trigger) => (
                            <div
                                key={trigger.triggerUuid}
                                className={`list-item ${selectedTrigger?.triggerUuid === trigger.triggerUuid
                                    ? "active"
                                    : ""
                                    }`}
                                onClick={() => setSelectedTrigger(trigger)}
                            >
                                <button id="trigger" className="value">
                                    <RenameInput
                                        value={trigger.triggerName}
                                        onRename={(newName) =>
                                            handleTriggerRename(trigger.triggerUuid, newName)
                                        }
                                    />
                                </button>
                                <button
                                    id="remove-trigger-button"
                                    className="remove-button"
                                    onClick={(e) => {
                                        e.stopPropagation();
                                        handleRemoveTrigger(trigger.triggerUuid);
                                    }}
                                >
                                    <RemoveIcon />
                                </button>
                            </div>
                        ))}
                    </div>
                    <button
                        className="resize-icon"
                        id="action-resize"
                        onMouseDown={(e: any) => handleResize(e, triggersContainerRef)}
                    >
                        <ResizeHeightIcon />
                    </button>
                </div>

                {selectedTrigger && (
                    <div className="trigger-item">
                        <div className="trigger-name">{selectedTrigger.triggerName}</div>
                        <LabledDropdown
                            label="Trigger Type"
                            defaultOption={selectedTrigger.triggerType}
                            // options={["onComplete", "onStart", "onStop", "delay", "onError"]}
                            options={["onComplete"]}
                            onSelect={handleTriggerTypeChange}
                        />

                        <div className="trigger-options">
                            <LabledDropdown
                                label="Triggered Object"
                                defaultOption={triggeredModel?.modelName || ""}
                                options={[...modelOptions.map((option) => option.modelName)]}
                                onSelect={(option) => {
                                    handleModelSelect(option, selectedTrigger.triggerUuid);
                                }}
                            />
                            <LabledDropdown
                                label="Triggered Point"
                                defaultOption={
                                    triggeredPoint?.uuid
                                        ? `Point ${triggeredPoint?.uuid.slice(0, 4)}`
                                        : ""
                                }
                                options={[
                                    ...pointOptions.map(
                                        (option) => `Point ${option.uuid.slice(0, 4)}`
                                    ),
                                ]}
                                onSelect={(option) => {
                                    handlePointSelect(option, selectedTrigger.triggerUuid);
                                }}
                            />
                            <LabledDropdown
                                label="Triggered Action"
                                defaultOption={triggeredAction?.actionName || ""}
                                options={[
                                    ...actionOptions.map((option: any) => option.actionName),
                                ]}
                                onSelect={(option) => {
                                    handleActionSelect(option, selectedTrigger.triggerUuid);
                                }}
                            />
                        </div>
                    </div>
                )}
            </div>
        </div>
    );
};

export default Trigger;
