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 { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { useSelectedAction, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/UpsertProductOrEventApi";

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

const Trigger = ({ selectedPointData, type }: TriggerProps) => {
    const [currentAction, setCurrentAction] = useState<string | undefined>();
    const { selectedProduct } = useSelectedProduct();
    const { getActionByUuid, getEventByModelUuid, getPointByUuid, getTriggerByUuid, addTrigger, removeTrigger, updateTrigger, renameTrigger, getProductById } = useProductStore();
    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 email = localStorage.getItem('email')
    const organization = (email!.split("@")[1]).split(".")[0];

    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' && selectedAction) {
            actionUuid = selectedAction.actionId;
        }

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

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

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

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

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

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

    const modelOptions = getProductById(selectedProduct.productId)?.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 as ConveyorEventSchema).points;
        } else if ('point' in model) {
            return [(model as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).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 as ConveyorPointSchema | VehiclePointSchema | MachinePointSchema | StoragePointSchema;
            return typedPoint.action ? [typedPoint.action] : [];
        } else if ('actions' in point) {
            const typedPoint = point as RoboticArmPointSchema;
            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.productId, triggerUuid, {
            triggeredAsset: {
                triggeredModel: {
                    modelName: selectedModel.modelName,
                    modelUuid: selectedModel.modelUuid
                },
                triggeredPoint: null,
                triggeredAction: null
            }
        });

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

            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                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.productId, triggerUuid, {
                triggeredAsset: {
                    ...selectedTrigger.triggeredAsset,
                    triggeredPoint: {
                        pointName: option,
                        pointUuid: pointUuid
                    },
                    triggeredAction: null
                }
            });

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

                updateBackend(
                    selectedProduct.productName,
                    selectedProduct.productId,
                    organization,
                    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.productId, triggerUuid, {
                triggeredAsset: {
                    ...selectedTrigger.triggeredAsset,
                    triggeredAction: {
                        actionName: option,
                        actionUuid: selectedAction.actionUuid
                    }
                }
            });

            if (event) {
                updateBackend(
                    selectedProduct.productName,
                    selectedProduct.productId,
                    organization,
                    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.productId, currentAction, newTrigger);

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

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

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

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

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

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                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.productId, triggerUuid, newName);

        if (event) {
            updateBackend(
                selectedProduct.productName,
                selectedProduct.productId,
                organization,
                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.productId, selectedTrigger.triggerUuid, {
            triggerType: option as TriggerSchema['triggerType']
        });

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

    return (
        <div className="trigger-wrapper">
            <div className="header">
                <div className="title">Trigger</div>
                <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 className="value">
                                    <RenameInput
                                        value={trigger.triggerName}
                                        onRename={(newName) => handleTriggerRename(trigger.triggerUuid, newName)}
                                    />
                                </button>
                                {triggers.length > 1 && (
                                    <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;
