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 RegularDropDown from "../../../ui/inputs/RegularDropDown";
import { handleResize } from "../../../../functions/handleResizePannel";
import EyeDropInput from "../../../ui/inputs/EyeDropInput";
import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store";
import * as THREE from 'three';
import * as Types from '../../../../types/world/worldTypes';
import InputToggle from "../../../ui/inputs/InputToggle";

const ConveyorMechanics: React.FC = () => {
  const { selectedActionSphere } = useSelectedActionSphere();
  const { selectedPath, setSelectedPath } = useSelectedPath();
  const { simulationPaths, setSimulationPaths } = useSimulationPaths();

  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 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;
    });

    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
    );

    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
    );

    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
    );

    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
    );

    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
    );

    setSimulationPaths(updatedPaths);
  };

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

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

    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: '',
                isUsed: false
              };

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

    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
    );

    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
    );

    setSimulationPaths(updatedPaths);
  };

  // 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
    );

    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
    );

    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 [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null);

  useEffect(() => {
    setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes
  }, [selectedActionSphere]);

  return (
    <div className="machine-mechanics-container">
      <div className="machine-mechanics-header">
        {selectedActionSphere?.path?.modelName || "point 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 })}
                      >
                        <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 })}
                      >
                        <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="enableTrigger"
                    label="Enable Trigger"
                    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)}
                  />
                </>
              )}
            </>
          )}

          {selectedPath && !selectedItem && (
            <div className="speed-control">
              <InputWithDropDown
                label="Conveyor Speed"
                value={selectedPath.path.speed.toString()}
                onChange={(value) => handleSpeedChange(parseFloat(value))}
              />
            </div>
          )}
        </div>
        <div className="footer">
          <InfoIcon />
          By selecting points, you can create events and triggers.
        </div>
      </div>
    </div>
  );
};

export default ConveyorMechanics;