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,
  useSimulationPaths,
} 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 { simulationPaths, setSimulationPaths } = useSimulationPaths();
  const { floorItems, setFloorItems } = useFloorItems();

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

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

  const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
    if (!updatedPath) return;
    // const email = localStorage.getItem("email");
    // const organization = email ? email.split("@")[1].split(".")[0] : "";
    // console.log('updatedPath: ', updatedPath);
    // const a = await setEventApi(
    //   organization,
    //   updatedPath.modeluuid,
    //   updatedPath.points
    // );
    // console.log('a: ', a);
  }

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

    const updatedPaths = simulationPaths.map((path) => {
      if (path.type === "Conveyor") {
        return {
          ...path,
          points: path.points.map((point) => {
            if (point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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.point.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 = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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 = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

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

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

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

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) => {
            if (point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(updatedPaths);
  };

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

    const updatedPaths = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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 = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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 = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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 = simulationPaths.map((path) =>
      path.type === "Conveyor"
        ? {
          ...path,
          points: path.points.map((point) =>
            point.uuid === selectedActionSphere.point.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.point.uuid
        )
    );
    updateBackend(updatedPath);

    setSimulationPaths(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;