/**
 * Custom hook for adding conditions to edges and event nodes to the canvas.
 * Handles the creation of new nodes and updating edge data when conditions
 * are attached via drag-and-drop or the component panel.
 */
import { useCallback } from 'react';
import { useStore, Node } from '../store/store';
import { generateNodeId } from '../utils/clipboardUtils';
import { getComponentTypeFromCategory } from '../utils/modelUtils';
import { LAYOUT, NODE_DIMENSIONS } from '../constants/dimensions';
import { findFreePosition } from '../utils/positionUtils';
import { t } from '../utils/translation';

interface UseNodeEdgeActionsProps {
  setHasUnsavedChanges: (value: boolean) => void;
}

export function useNodeEdgeActions({ setHasUnsavedChanges }: UseNodeEdgeActionsProps) {
  const nodes = useStore(state => state.nodes);
  const setNodes = useStore(state => state.setNodes);
  const setEdges = useStore(state => state.setEdges);
  // Add condition to edge handler
  const handleAddCondition = useCallback((edgeId: string, component: any) => {
    const conditionLabel = component.label || component.plugin?.split('.').pop() || component.plugin;

    // Build the updated edge data
    const updatedEdgeData = {
      label: conditionLabel,
      type: 'condition' as const,
      data: {
        condition: component.plugin,
        conditionLabel: conditionLabel
      }
    };

    // Deselect all nodes so ReactFlow's internal selection stays in sync.
    setNodes(prev => {
      const hasSelected = prev.some(n => n.selected);
      return hasSelected ? prev.map(n => n.selected ? { ...n, selected: false } : n) : prev;
    });

    // Update the target edge with condition data and mark it as selected,
    // deselecting all other edges.
    // ReactFlow's onSelectionChange will update the store's selection state.
    setEdges(prev =>
      prev.map(edge => {
        if (edge.id === edgeId) {
          return {
            ...edge,
            ...updatedEdgeData,
            selected: true,
            data: {
              ...edge.data,
              ...updatedEdgeData.data
            }
          };
        }
        return edge.selected ? { ...edge, selected: false } : edge;
      })
    );

    setHasUnsavedChanges(true);
  }, [setNodes, setEdges, setHasUnsavedChanges]);

  // Add event/start node to canvas handler
  const handleAddEvent = useCallback((component: any) => {
    const label = component.label || component.plugin?.split('.').pop() || t('New Event');
    const componentType = getComponentTypeFromCategory(component.category || '');
    const newNodeId = generateNodeId(label, 'start');

    // Find a good position for the new event - to the right of existing nodes
    let candidateX: number = LAYOUT.DEFAULT_POSITION_X;
    let candidateY: number = LAYOUT.DEFAULT_POSITION_Y;

    // Check if there are existing nodes and position to the right of them
    if (nodes.length > 0) {
      // Find rightmost position and topmost Y position
      const maxX = Math.max(...nodes.map(n => n.position.x));
      const minY = Math.min(...nodes.map(n => n.position.y));

      // Place new event to the right of existing content
      candidateX = maxX + LAYOUT.NODE_SPACING_X;
      candidateY = minY;
    }

    // Find a free position that doesn't overlap any existing node
    const freePosition = findFreePosition(
      { x: candidateX, y: candidateY },
      nodes,
      NODE_DIMENSIONS.START_NODE_WIDTH,
      NODE_DIMENSIONS.START_NODE_HEIGHT,
    );

    const newNode: Node = {
      id: newNodeId,
      type: 'start',
      position: freePosition,
      selected: true,
      data: {
        plugin: component.plugin,
        label,
        category: component.category,
        componentType,
        description: component.description,
        documentationUrl: component.documentationUrl,
      },
    };

    // Deselect all existing nodes/edges and add the new node as selected,
    // so that ReactFlow's internal selection stays in sync with the store.
    setNodes(prev => [...prev.map(n => n.selected ? { ...n, selected: false } : n), newNode]);
    setEdges(prev => {
      const hasSelected = prev.some(e => e.selected);
      return hasSelected ? prev.map(e => e.selected ? { ...e, selected: false } : e) : prev;
    });

    // Mark as having unsaved changes
    setHasUnsavedChanges(true);
  }, [nodes, setNodes, setEdges, setHasUnsavedChanges]);

  return {
    handleAddCondition,
    handleAddEvent,
  };
}
