/**
 * Custom hook for quick-add functionality
 * Handles creating new nodes and connecting them to existing nodes
 */

import { useCallback } from 'react';
import { useStore, Component } from '../store/store';
import { generateNodeId, generateEdgeId } from '../utils/clipboardUtils';
import { getComponentTypeFromCategory } from '../utils/modelUtils';
import { LAYOUT, NODE_DIMENSIONS } from '../constants/dimensions';
import { findFlowAwarePosition } from '../utils/positionUtils';

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

export function useQuickAdd({ setHasUnsavedChanges }: UseQuickAddProps) {
  const nodes = useStore(state => state.nodes);
  const edges = useStore(state => state.edges);
  const setNodes = useStore(state => state.setNodes);
  const setEdges = useStore(state => state.setEdges);
  /**
   * Add a new node as a successor to an existing node
   */
  const addSuccessorNode = useCallback((component: Component, sourceNodeId: string) => {
    // Find the source node
    const sourceNode = nodes.find(n => n.id === sourceNodeId);
    if (!sourceNode) {
      console.error('Source node not found:', sourceNodeId);
      return;
    }

    // Calculate position for the new node (below the source node)
    const sourceWidth = sourceNode.width || NODE_DIMENSIONS.DEFAULT_WIDTH;
    const sourceHeight = sourceNode.height || NODE_DIMENSIONS.DEFAULT_HEIGHT;
    
    const candidatePosition = {
      x: sourceNode.position.x + (sourceWidth / 2) - (NODE_DIMENSIONS.DEFAULT_WIDTH / 2),
      y: sourceNode.position.y + sourceHeight + LAYOUT.NODE_SPACING_Y
    };

    // Find a free position that respects flow boundaries.
    // If the position would cross into a neighboring flow, the result
    // includes a set of node IDs to shift right to create room.
    const { position: newPosition, shiftNodeIds, shiftAmount } = findFlowAwarePosition(
      candidatePosition,
      sourceNodeId,
      nodes,
      edges,
    );

    // Determine node type from component
    const nodeType = component.type === 'start' ? 'start' : 
                     (component.type === 'gateway' || component.category === 'Gateways') ? 'gateway' : 
                     'element';
    
    // Create the new node
    const label = component.label || component.plugin?.split('.').pop() || 'New Node';
    const componentType = getComponentTypeFromCategory(component.category || '');
    const newNodeId = generateNodeId(label, nodeType);
    
    const newNode = {
      id: newNodeId,
      type: nodeType,
      position: newPosition,
      selected: true,
      data: {
        plugin: component.plugin,
        label,
        category: component.category,
        componentType,
        description: component.description,
        documentationUrl: component.documentationUrl,
      },
    };

    // Create the edge connecting source to new node
    const newEdgeId = generateEdgeId(sourceNodeId, newNodeId);
    const newEdge = {
      id: newEdgeId,
      source: sourceNodeId,
      target: newNodeId,
      type: 'default',
      data: {},
    };

    // Deselect all existing nodes/edges and add the new node as selected.
    // If neighboring flows need shifting, apply the shift in the same update.
    // ReactFlow's onSelectionChange will update the store's selection state.
    setNodes(prev => {
      const updated = prev.map(n => {
        let node = n.selected ? { ...n, selected: false } : n;
        // Shift nodes in neighboring flows to make room
        if (shiftAmount > 0 && n.id && shiftNodeIds.has(n.id)) {
          node = node === n ? { ...n } : node;
          node.position = { x: node.position.x + shiftAmount, y: node.position.y };
        }
        return node;
      });
      return [...updated, newNode];
    });
    setEdges(prev => [...prev.map(e => e.selected ? { ...e, selected: false } : e), newEdge]);
    
    // Mark as having unsaved changes
    setHasUnsavedChanges(true);

  }, [nodes, edges, setNodes, setEdges, setHasUnsavedChanges]);

  return {
    addSuccessorNode
  };
}
