<script setup>
import { ref, onMounted, computed, shallowRef, onUnmounted, nextTick, watch } from 'vue';
import { useProcessBuilderStore } from '~/stores/processBuilder';
import { useRouter, useRoute } from 'vue-router';
import ProcessFlowCanvas from '~/components/process-flow/ProcessFlowCanvas.vue';
import ProcessBuilderComponents from '~/components/process-flow/ProcessBuilderComponents.vue';
import FormSelector from '~/components/process-flow/FormSelector.vue';
import GatewayConditionManager from '~/components/process-flow/GatewayConditionManager.vue';
import GatewayConditionManagerModal from '~/components/process-flow/GatewayConditionManagerModal.vue';
import ApiNodeConfiguration from '~/components/process-flow/ApiNodeConfiguration.vue';
import ApiNodeConfigurationModal from '~/components/process-flow/ApiNodeConfigurationModal.vue';
import VariableManager from '~/components/process-flow/VariableManager.vue';
import { onBeforeRouteLeave } from 'vue-router';
import FormNodeConfiguration from '~/components/process-flow/FormNodeConfiguration.vue';
import FormNodeConfigurationModal from '~/components/process-flow/FormNodeConfigurationModal.vue';

import BusinessRuleNodeConfiguration from '~/components/process-flow/BusinessRuleNodeConfiguration.vue';
import BusinessRuleNodeConfigurationModal from '~/components/process-flow/BusinessRuleNodeConfigurationModal.vue';
import NotificationNodeConfigurationModal from '~/components/process-flow/NotificationNodeConfigurationModal.vue';
import ScriptNodeConfigurationModal from '~/components/process-flow/ScriptNodeConfigurationModal.vue';
import HtmlNodeConfigurationModal from '~/components/process-flow/HtmlNodeConfigurationModal.vue';
import SubprocessNodeConfigurationModal from '~/components/process-flow/SubprocessNodeConfigurationModal.vue';
import ProcessTemplatesModal from '~/components/ProcessTemplatesModal.vue';
import ProcessSettingsModal from '~/components/process-flow/ProcessSettingsModal.vue';
import ProcessHistoryModal from '~/components/ProcessHistoryModal.vue';
import ExportCanvasModal from '~/components/process-flow/ExportCanvasModal.vue';

// Define page meta
definePageMeta({
  title: "Process Builder",
  description: "Create business processes with drag and drop",
  layout: "empty",
  middleware: ["auth"],
  requiresAuth: true,
});

// Initialize the store and router
const processStore = useProcessBuilderStore();
const router = useRouter();
const route = useRoute();

// Initialize toast with fallback
let toast;
try {
  toast = useToast();
} catch (error) {
  // Create a simple toast object if composable is not available
  toast = {
    success: (msg) => {}, // Silent success
    error: (msg) => console.error('Error:', msg),
    info: (msg) => console.info('Info:', msg),
    warning: (msg) => console.warn('Warning:', msg)
  };
}

// Track selected node local state (syncs with store)
// Using shallowRef to avoid making Vue components reactive
const selectedNode = shallowRef(null);

// Track if we're creating a new process
const isCreatingProcess = ref(false);
const newProcessName = ref('');
const newProcessDescription = ref('');

// Track selected node data
const selectedNodeData = ref(null);

// Track drag data
const draggedComponent = ref(null);

// Add a variable to track selected edge
const selectedEdgeData = ref(null);

// Add variables for navigation handling
const showUnsavedChangesModal = ref(false);
const pendingNavigation = ref(null);
const navigationTarget = ref(null);
const navigationConfirmed = ref(false);
const isSaving = ref(false);
const isAddingComponent = ref(false); // Flag to prevent canvas reactivity issues during component addition

// Add clipboard state for copy/paste functionality
const clipboard = ref({
  nodes: [],
  edges: [],
  type: null, // 'nodes', 'edges', or 'mixed'
  timestamp: null
});

// Load clipboard from localStorage on mount
const loadClipboardFromStorage = () => {
  try {
    const stored = localStorage.getItem('processBuilderClipboard');
    if (stored) {
      const parsed = JSON.parse(stored);
      // Only restore if it's recent (within 24 hours)
      const isRecent = parsed.timestamp && (Date.now() - parsed.timestamp) < 24 * 60 * 60 * 1000;
      if (isRecent) {
        clipboard.value = parsed;
      }
    }
  } catch (error) {
    console.warn('Failed to load clipboard from storage:', error);
  }
};

// Save clipboard to localStorage
const saveClipboardToStorage = () => {
  try {
    localStorage.setItem('processBuilderClipboard', JSON.stringify(clipboard.value));
  } catch (error) {
    console.warn('Failed to save clipboard to storage:', error);
  }
};

// Storage event handler for cross-tab clipboard sync
const handleStorageEvent = (event) => {
  if (event.key === 'processBuilderClipboard' && event.newValue) {
    try {
      const parsed = JSON.parse(event.newValue);
      clipboard.value = parsed;
    } catch (error) {
      console.warn('Failed to parse clipboard from storage event:', error);
    }
  }
};

// Add a ref for the ProcessFlowCanvas component
const processFlowCanvas = ref(null);

// Add state for node configuration modals
const showFormConfigModal = ref(false);
const showApiConfigModal = ref(false);
const showGatewayConfigModal = ref(false);
const showBusinessRuleConfigModal = ref(false);
const showNotificationConfigModal = ref(false);
const showScriptConfigModal = ref(false);
const showHtmlConfigModal = ref(false);
const showSubprocessConfigModal = ref(false);
const showTemplatesModal = ref(false);
const showProcessSettings = ref(false);
const showDropdown = ref(false);
const showProcessHistoryModal = ref(false);
const showExportModal = ref(false);

// Add mobile responsive state
const showLeftPanel = ref(true);
const showRightPanel = ref(true);
const isMobile = ref(false);
const isTablet = ref(false);

// Add node highlighting state
const highlightedNodeId = ref(null);
const highlightTimeout = ref(null);

// Mobile breakpoint detection
const checkScreenSize = () => {
  const width = window.innerWidth;
  isMobile.value = width < 768; // Mobile: < 768px
  isTablet.value = width >= 768 && width < 1024; // Tablet: 768px - 1024px
  
  // Auto-hide panels on mobile
  if (isMobile.value) {
    showLeftPanel.value = false;
    showRightPanel.value = false;
  } else if (isTablet.value) {
    // On tablet, show only one panel at a time if both were closed
    if (!showLeftPanel.value && !showRightPanel.value) {
      showRightPanel.value = true;
    }
  } else {
    // Desktop: show both panels by default only on first load
    // Don't override user preferences on screen size changes
  }
};

// Toggle panel visibility
const toggleLeftPanel = () => {
  showLeftPanel.value = !showLeftPanel.value;
  
  // On mobile/tablet, close the other panel when opening one
  if ((isMobile.value || isTablet.value) && showLeftPanel.value) {
    showRightPanel.value = false;
  }
};

const toggleRightPanel = () => {
  showRightPanel.value = !showRightPanel.value;
  
  // On mobile/tablet, close the other panel when opening one
  if ((isMobile.value || isTablet.value) && showRightPanel.value) {
    showLeftPanel.value = false;
  }
};

// Toggle both panels at once
const toggleBothPanels = () => {
  const bothVisible = showLeftPanel.value && showRightPanel.value;
  showLeftPanel.value = !bothVisible;
  showRightPanel.value = !bothVisible;
};

// Close panels when clicking on canvas (mobile only)
const onPaneClickMobile = () => {
  selectedNode.value = null;
  selectedNodeData.value = null;
  selectedEdgeData.value = null;
  processStore.clearSelection();
  
  // Close panels on mobile when clicking canvas
  if (isMobile.value) {
    showLeftPanel.value = false;
    showRightPanel.value = false;
  }
};

// Copy/paste functions
const copySelectedElements = () => {
  const copiedNodes = [];
  const copiedEdges = [];
  
  // Get all selected elements from Vue Flow
  let selectedNodes = [];
  let selectedEdges = [];
  
  if (processFlowCanvas.value) {
    try {
      // Try the new getSelectedElements method first
      if (processFlowCanvas.value.getSelectedElements) {
        const selection = processFlowCanvas.value.getSelectedElements();
        selectedNodes = selection.nodes || [];
        selectedEdges = selection.edges || [];
      }
      
      // If no selection found, try direct access to nodes and edges
      if (selectedNodes.length === 0 && selectedEdges.length === 0) {
        if (processFlowCanvas.value.nodes && processFlowCanvas.value.edges) {
          selectedNodes = processFlowCanvas.value.nodes.filter(node => node.selected === true);
          selectedEdges = processFlowCanvas.value.edges.filter(edge => edge.selected === true);
        }
      }
      
      // If still no selection found, try DOM-based detection as fallback
      if (selectedNodes.length === 0 && selectedEdges.length === 0) {
        // Look for selected nodes in the DOM
        const selectedNodeElements = document.querySelectorAll('.vue-flow__node.selected');
        const selectedEdgeElements = document.querySelectorAll('.vue-flow__edge.selected');
        
        // Convert DOM elements to node/edge data
        if (processFlowCanvas.value.nodes && processFlowCanvas.value.edges) {
          selectedNodeElements.forEach(element => {
            const nodeId = element.getAttribute('data-id');
            if (nodeId) {
              const node = processFlowCanvas.value.nodes.find(n => n.id === nodeId);
              if (node) {
                selectedNodes.push(node);
              }
            }
          });
          
          selectedEdgeElements.forEach(element => {
            const edgeId = element.getAttribute('data-id');
            if (edgeId) {
              const edge = processFlowCanvas.value.edges.find(e => e.id === edgeId);
              if (edge) {
                selectedEdges.push(edge);
              }
            }
          });
        }
      }
    } catch (error) {
      console.warn('Failed to get selected elements from Vue Flow:', error);
    }
  }
  
  // If no multiple selection, fall back to single selection
  if (selectedNodes.length === 0 && selectedEdges.length === 0) {
    // Copy selected nodes
    if (selectedNodeData.value) {
      const nodeCopy = JSON.parse(JSON.stringify(selectedNodeData.value));
      // Remove any temporary properties
      delete nodeCopy.selected;
      delete nodeCopy.dragging;
      copiedNodes.push(nodeCopy);
    }
    
    // Copy selected edges
    if (selectedEdgeData.value) {
      const edgeCopy = JSON.parse(JSON.stringify(selectedEdgeData.value));
      // Remove any temporary properties
      delete edgeCopy.selected;
      copiedEdges.push(edgeCopy);
    }
  } else {
    // Handle multiple selection
    for (const node of selectedNodes) {
      const nodeCopy = JSON.parse(JSON.stringify(node));
      // Remove any temporary properties
      delete nodeCopy.selected;
      delete nodeCopy.dragging;
      copiedNodes.push(nodeCopy);
    }
    
    for (const edge of selectedEdges) {
      const edgeCopy = JSON.parse(JSON.stringify(edge));
      // Remove any temporary properties
      delete edgeCopy.selected;
      copiedEdges.push(edgeCopy);
    }
  }
  
  // Store in clipboard
  clipboard.value = {
    nodes: copiedNodes,
    edges: copiedEdges,
    type: copiedNodes.length > 0 && copiedEdges.length > 0 ? 'mixed' : 
          copiedNodes.length > 0 ? 'nodes' : 
          copiedEdges.length > 0 ? 'edges' : null,
    timestamp: Date.now()
  };
  
  // Save to localStorage
  saveClipboardToStorage();
  
  // Show feedback
  const totalElements = copiedNodes.length + copiedEdges.length;
  if (totalElements > 0) {
    toast.success(`Copied ${totalElements} element${totalElements > 1 ? 's' : ''} to clipboard`);
  } else {
    toast.warning('No elements selected to copy');
  }
};

const clearClipboard = () => {
  clipboard.value = {
    nodes: [],
    edges: [],
    type: null,
    timestamp: null
  };
  // Clear from localStorage
  try {
    localStorage.removeItem('processBuilderClipboard');
  } catch (error) {
    console.warn('Failed to clear clipboard from storage:', error);
  }
  toast.info('Clipboard cleared');
};

// Debug function to help understand selection state
const debugSelection = () => {
  console.log('=== DEBUG SELECTION STATE ===');
  
  if (!processFlowCanvas.value) {
    console.log('ProcessFlowCanvas not available');
    return;
  }
  
  console.log('ProcessFlowCanvas available, checking properties...');
  console.log('Available methods:', Object.keys(processFlowCanvas.value));
  
  if (!processFlowCanvas.value.flowInstance) {
    console.log('Flow instance not available');
    console.log('Trying to access flowInstance directly...');
    
    // Try different ways to access the flow instance
    try {
      const flowInstance = processFlowCanvas.value.flowInstance;
      console.log('Direct access result:', flowInstance);
    } catch (error) {
      console.log('Direct access error:', error);
    }
    
    // Check if we can access nodes and edges directly
    try {
      const nodes = processFlowCanvas.value.nodes;
      const edges = processFlowCanvas.value.edges;
      console.log('Direct nodes access:', nodes);
      console.log('Direct edges access:', edges);
    } catch (error) {
      console.log('Direct nodes/edges access error:', error);
    }
    
    return;
  }
  
  const flowInstance = processFlowCanvas.value.flowInstance;
  
  // Check Vue Flow selection
  try {
    const selection = flowInstance.getSelection();
    console.log('Vue Flow selection:', selection);
  } catch (error) {
    console.log('Error getting Vue Flow selection:', error);
  }
  
  // Check all nodes and edges
  const allNodes = flowInstance.getNodes();
  const allEdges = flowInstance.getEdges();
  
  console.log('All nodes:', allNodes.length);
  console.log('All edges:', allEdges.length);
  
  // Check for selected property
  const selectedNodes = allNodes.filter(node => node.selected);
  const selectedEdges = allEdges.filter(edge => edge.selected);
  
  console.log('Nodes with selected=true:', selectedNodes.length);
  console.log('Edges with selected=true:', selectedEdges.length);
  
  // Check DOM
  const domSelectedNodes = document.querySelectorAll('.vue-flow__node.selected');
  const domSelectedEdges = document.querySelectorAll('.vue-flow__edge.selected');
  
  console.log('DOM selected nodes:', domSelectedNodes.length);
  console.log('DOM selected edges:', domSelectedEdges.length);
  
  // Show details of selected elements
  if (selectedNodes.length > 0) {
    console.log('Selected nodes:', selectedNodes.map(n => ({ id: n.id, type: n.type, selected: n.selected })));
  }
  
  if (selectedEdges.length > 0) {
    console.log('Selected edges:', selectedEdges.map(e => ({ id: e.id, source: e.source, target: e.target, selected: e.selected })));
  }
  
  console.log('=== END DEBUG ===');
};

const pasteElements = async () => {
  if (!clipboard.value.type || !processStore.currentProcess) {
    toast.warning('No elements in clipboard to paste');
    return;
  }
  
  try {
    const pastedNodes = [];
    const pastedEdges = [];
    const nodeIdMap = new Map(); // Map old IDs to new IDs
    
    // Process nodes first
    if (clipboard.value.nodes.length > 0) {
      for (const node of clipboard.value.nodes) {
        const newNode = JSON.parse(JSON.stringify(node));
        
        // Generate new ID
        const oldId = newNode.id;
        const newId = `${newNode.type}_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
        newNode.id = newId;
        
        // Offset position to avoid overlap - use a more sophisticated offset
        const baseX = newNode.position?.x || 100;
        const baseY = newNode.position?.y || 100;
        const offsetX = 100 + (pastedNodes.length * 80); // Larger offset for better visibility
        const offsetY = 100 + (pastedNodes.length * 60); // Different Y offset to create a diagonal pattern
        
        newNode.position = {
          x: baseX + offsetX,
          y: baseY + offsetY
        };
        
        // Update label to indicate it's a copy
        if (newNode.label && !newNode.label.includes(' (Copy)')) {
          newNode.label = `${newNode.label} (Copy)`;
        }
        if (newNode.data?.label && !newNode.data.label.includes(' (Copy)')) {
          newNode.data.label = `${newNode.data.label} (Copy)`;
        }
        
        // Store ID mapping for edge updates
        nodeIdMap.set(oldId, newId);
        
        // Add to store
        await processStore.addNode(newNode);
        pastedNodes.push(newNode);
      }
    }
    
    // Process edges after nodes
    if (clipboard.value.edges.length > 0) {
      for (const edge of clipboard.value.edges) {
        const newEdge = JSON.parse(JSON.stringify(edge));
        
        // Generate new ID
        newEdge.id = `edge_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
        
        // Update source and target IDs if they were copied nodes
        if (nodeIdMap.has(newEdge.source)) {
          newEdge.source = nodeIdMap.get(newEdge.source);
        }
        if (nodeIdMap.has(newEdge.target)) {
          newEdge.target = nodeIdMap.get(newEdge.target);
        }
        
        // Only add edge if both source and target nodes exist
        const sourceExists = processStore.currentProcess.nodes.some(n => n.id === newEdge.source);
        const targetExists = processStore.currentProcess.nodes.some(n => n.id === newEdge.target);
        
        if (sourceExists && targetExists) {
          await processStore.addEdge(newEdge);
          pastedEdges.push(newEdge);
        } else {
          // Show warning for orphaned edges
          const missingNodes = [];
          if (!sourceExists) missingNodes.push(newEdge.source);
          if (!targetExists) missingNodes.push(newEdge.target);
          console.warn(`Skipping edge ${newEdge.id}: missing nodes ${missingNodes.join(', ')}`);
        }
      }
    }
    
    // Show success message
    const totalPasted = pastedNodes.length + pastedEdges.length;
    const skippedEdges = clipboard.value.edges.length - pastedEdges.length;
    
    if (totalPasted > 0) {
      let message = `Pasted ${totalPasted} element${totalPasted > 1 ? 's' : ''} successfully`;
      if (skippedEdges > 0) {
        message += ` (${skippedEdges} edge${skippedEdges > 1 ? 's' : ''} skipped - missing nodes)`;
      }
      toast.success(message);
      
      // Select the first pasted node if any
      if (pastedNodes.length > 0) {
        onNodeSelected(pastedNodes[0]);
        
        // Fit view to show all pasted nodes
        if (processFlowCanvas.value && processFlowCanvas.value.fitView) {
          nextTick(() => {
            try {
              processFlowCanvas.value.fitView({ 
                padding: 0.1,
                includeHiddenNodes: false,
                minZoom: 0.5,
                maxZoom: 1.5
              });
            } catch (error) {
              console.warn('Failed to fit view:', error);
            }
          });
        }
      }
    } else if (skippedEdges > 0) {
      toast.warning(`${skippedEdges} edge${skippedEdges > 1 ? 's' : ''} could not be pasted - missing connected nodes`);
    }
    
  } catch (error) {
    console.error('Error pasting elements:', error);
    toast.error('Failed to paste elements');
  }
};

// Keyboard shortcuts for panel toggles and copy/paste
const handleKeyboardShortcuts = (event) => {
  // Check if any modal is open - if so, don't handle process builder shortcuts
  const isModalOpen = showFormConfigModal.value || 
                     showApiConfigModal.value || 
                     showGatewayConfigModal.value || 
                     showBusinessRuleConfigModal.value || 
                     showNotificationConfigModal.value || 
                     showScriptConfigModal.value || 
                     showHtmlConfigModal.value || 
                     showSubprocessConfigModal.value || 
                     showTemplatesModal.value || 
                     showProcessSettings.value || 
                     showProcessHistoryModal.value || 
                     showExportModal.value || 
                     showUnsavedChangesModal.value;
  
  if (isModalOpen) {
    // Debug logging (can be removed in production)
    if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
      console.log('🔒 Process builder shortcuts blocked - modal is open');
    }
    return; // Let the modal handle its own keyboard shortcuts
  }
  
  // Check if the target is an input element or code editor
  const target = event.target;
  const isInputElement = target.tagName === 'INPUT' || 
                        target.tagName === 'TEXTAREA' || 
                        target.tagName === 'SELECT' ||
                        target.contentEditable === 'true' ||
                        target.closest('.CodeMirror') !== null ||
                        target.closest('.cm-editor') !== null ||
                        target.closest('.cm-content') !== null ||
                        target.closest('.cm-cursor') !== null ||
                        target.closest('.cm-line') !== null ||
                        target.closest('.formkit-input') !== null ||
                        target.closest('.formkit-textarea') !== null ||
                        target.closest('[contenteditable="true"]') !== null ||
                        target.closest('.rs-code-mirror') !== null ||
                        target.closest('[data-cm-editor]') !== null;
  
  if (isInputElement) {
    // Debug logging (can be removed in production)
    if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
      console.log('🔒 Process builder shortcuts blocked - input element detected:', target.tagName, target.className);
    }
    return; // Let the input element handle its own keyboard shortcuts
  }
  
  // Additional check: if the target is inside any modal, don't handle process builder shortcuts
  const isInsideModal = target.closest('.rs-modal') !== null ||
                       target.closest('.modal') !== null ||
                       target.closest('[role="dialog"]') !== null ||
                       target.closest('.vue-flow__modal') !== null;
  
  if (isInsideModal) {
    // Debug logging (can be removed in production)
    if (process.env.NODE_ENV === 'development' && (event.ctrlKey || event.metaKey) && (event.key === 'c' || event.key === 'v')) {
      console.log('🔒 Process builder shortcuts blocked - inside modal');
    }
    return; // Let the modal handle its own keyboard shortcuts
  }
  
  // Ctrl/Cmd + 1: Toggle left panel
  if ((event.ctrlKey || event.metaKey) && event.key === '1') {
    event.preventDefault();
    toggleLeftPanel();
  }
  
  // Ctrl/Cmd + 2: Toggle right panel
  if ((event.ctrlKey || event.metaKey) && event.key === '2') {
    event.preventDefault();
    toggleRightPanel();
  }
  
  // Ctrl/Cmd + 3: Toggle both panels
  if ((event.ctrlKey || event.metaKey) && event.key === '3') {
    event.preventDefault();
    toggleBothPanels();
  }
  
  // Ctrl/Cmd + C: Copy selected elements
  if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
    event.preventDefault();
    // Debug logging (can be removed in production)
    if (process.env.NODE_ENV === 'development') {
      console.log('📋 Process builder copy shortcut triggered');
    }
    copySelectedElements();
  }
  
  // Ctrl/Cmd + V: Paste elements
  if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
    event.preventDefault();
    // Debug logging (can be removed in production)
    if (process.env.NODE_ENV === 'development') {
      console.log('📋 Process builder paste shortcut triggered');
    }
    pasteElements();
  }
};

// Handle node highlighting from variable usage
const handleNodeHighlight = (event) => {

  const { nodeId, node } = event.detail;
  
  // Clear any existing highlight timeout
  if (highlightTimeout.value) {
    clearTimeout(highlightTimeout.value);
  }
  
  // Set the highlighted node
  highlightedNodeId.value = nodeId;
  
  
  // Center the view on the highlighted node
  if (processFlowCanvas.value && node) {
    nextTick(() => {
      try {
  
        
        // Call the exposed methods from ProcessFlowCanvas
        if (processFlowCanvas.value.centerOnNode) {
          processFlowCanvas.value.centerOnNode(nodeId, node.position);
        } else {
          console.warn('centerOnNode method not available on ProcessFlowCanvas');
        }
      } catch (error) {
        console.error('Error centering view on node:', error);
      }
    });
  }
  
  // Show success toast
  if (toast) {
    toast.success(`Navigated to: ${node.data?.label || node.type} node`);
  }
  
  // Auto-remove highlight after 5 seconds
  highlightTimeout.value = setTimeout(() => {
    highlightedNodeId.value = null;
    highlightTimeout.value = null;
  }, 5000);
};

// Component definitions
const components = [
  {
    type: 'start',
    label: 'Start Point',
    icon: 'play-circle-rounded',
    iconColor: 'text-green-500',
    data: { description: 'Process starts here' }
  },
  {
    type: 'form',
    label: 'Form',
    icon: 'description',
    iconColor: 'text-purple-500',
    data: { description: 'Form submission', formName: '', shape: 'rectangle', backgroundColor: '#faf5ff', borderColor: '#9333ea', textColor: '#6b21a8' }
  },
  {
    type: 'api',
    label: 'API Call',
    icon: 'api',
    iconColor: 'text-indigo-500',
    data: { 
      description: 'External API call',
      apiMethod: 'GET',
      apiUrl: '',
      requestBody: '',
      headers: '{ "Content-Type": "application/json" }',
      outputVariable: 'apiResponse',
      continueOnError: false,
      errorVariable: 'apiError',
      shape: 'rectangle',
      backgroundColor: '#eff6ff',
      borderColor: '#3b82f6', 
      textColor: '#1e40af'
    }
  },
  {
    type: 'gateway',
    label: 'Decision Point',
    icon: 'call-split',
    iconColor: 'text-orange-500',
    data: { description: 'Decision point for branching the workflow', conditions: [], shape: 'diamond', backgroundColor: '#fff7ed', borderColor: '#f97316', textColor: '#c2410c' }
  },
  {
    type: 'script',
    label: 'Script',
    icon: 'code',
    iconColor: 'text-gray-500',
    data: { description: 'Script execution', language: 'JavaScript', shape: 'rectangle', backgroundColor: '#f9fafb', borderColor: '#6b7280', textColor: '#374151' }
  },
  {
    type: 'html',
    label: 'HTML',
    icon: 'html',
    iconColor: 'text-blue-500',
    data: { 
      description: 'Custom HTML content', 
      htmlCode: '<!-- Enter your HTML code here -->\n<div class="custom-html-content">\n  <h2>Custom HTML Content</h2>\n  <p>This is a custom HTML node that can display rich content.</p>\n</div>',
      cssCode: '',
      jsCode: '',
      shape: 'rectangle', 
      backgroundColor: '#e0f2fe', 
      borderColor: '#0ea5e9', 
      textColor: '#0c4a6e' 
    }
  },
  {
    type: 'business-rule',
    label: 'Business Rule',
    icon: 'rule',
    iconColor: 'text-purple-500',
    data: { description: 'Business logic evaluation', shape: 'rectangle', backgroundColor: '#fdf4ff', borderColor: '#a855f7', textColor: '#7c3aed' }
  },
  {
    type: 'notification',
    label: 'Notification',
    icon: 'notifications',
    iconColor: 'text-blue-500',
    data: { description: 'Send notifications', shape: 'rectangle', backgroundColor: '#f0f9ff', borderColor: '#0ea5e9', textColor: '#0284c7' }
  },
  {
    type: 'subprocess',
    label: 'Sub Process',
    icon: 'hub',
    iconColor: 'text-teal-500',
    data: { 
      description: 'Executes another process', 
      subprocessId: null,
      subprocessName: '',
      shape: 'rectangle', 
      backgroundColor: '#f0fdfa', 
      borderColor: '#14b8a6', 
      textColor: '#134e4a' 
    }
  },
  {
    type: 'end',
    label: 'End Point',
    icon: 'stop-circle',
    iconColor: 'text-red-500',
    data: { description: 'Process completes here' }
  }
];

// Computed to check if we have a current process
const hasCurrentProcess = computed(() => {
  return !!processStore.currentProcess;
});

// Create computed properties for canvas props to control reactivity
const canvasNodes = computed(() => {
  if (!processStore.currentProcess) return [];
  // Return a deep copy to ensure proper reactivity for nested objects like data
  return processStore.currentProcess.nodes.map(node => {
    const isShape = node.data?.isShape || false;
    const style = isShape ? { zIndex: node.data.zIndex ?? 0 } : {};

    return {
      ...node,
      style: { ...(node.style || {}), ...style },
      data: { ...node.data },
      // Ensure labels are synchronized both ways
      label: node.label || node.data?.label || node.type
    };
  });
});

const canvasEdges = computed(() => {
  if (!processStore.currentProcess) return [];
  // Return a shallow copy to avoid direct reactivity  
  return processStore.currentProcess.edges.map(edge => ({ ...edge }));
});

// Computed properties for node data
const nodeLabel = computed({
  get: () => selectedNodeData.value?.label || '',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.label = value;
      updateNodeInStore();
    }
  }
});

const nodeDescription = computed({
  get: () => selectedNodeData.value?.data?.description || '',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.description = value;
      updateNodeInStore();
    }
  }
});

const nodeAssignee = computed({
  get: () => selectedNodeData.value?.data?.assignee || '',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.assignee = value;
      updateNodeInStore();
    }
  }
});

const nodeFormName = computed({
  get: () => selectedNodeData.value?.data?.formName || '',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.formName = value;
      updateNodeInStore();
    }
  }
});

const nodeLanguage = computed({
  get: () => selectedNodeData.value?.data?.language || 'JavaScript',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.language = value;
      updateNodeInStore();
    }
  }
});

// Add computed property for node shape
const nodeShape = computed({
  get: () => {
    if (!selectedNodeData.value?.data) return 'rectangle';
    // Don't allow shape changes for start and end nodes
    if (selectedNodeData.value.type === 'start' || selectedNodeData.value.type === 'end') {
      return selectedNodeData.value.type === 'start' || selectedNodeData.value.type === 'end' ? 'circle' : 'rectangle';
    }
    return selectedNodeData.value.data.shape || 'rectangle';
  },
  set: (value) => {
    if (selectedNodeData.value && selectedNodeData.value.type !== 'start' && selectedNodeData.value.type !== 'end') {
      selectedNodeData.value.data.shape = value;
      updateNodeInStore();
    }
  }
});

// Shape options for the dropdown
const shapeOptions = [
  { value: 'rectangle', label: 'Rectangle', icon: 'crop-landscape' },
  { value: 'rounded-rectangle', label: 'Rounded Rectangle', icon: 'rounded-corner' },
  { value: 'circle', label: 'Circle', icon: 'radio-button-unchecked' },
  { value: 'diamond', label: 'Diamond', icon: 'change-history' },
  { value: 'hexagon', label: 'Hexagon', icon: 'hexagon' },
  { value: 'parallelogram', label: 'Parallelogram', icon: 'details' },
  { value: 'trapezoid', label: 'Trapezoid', icon: 'architecture' }
];

// Helper function to get icon for node type
const getNodeIcon = (nodeType) => {
  const iconMap = {
    'form': 'description',
    'api': 'api',
    'gateway': 'call-split',
    'script': 'code',
    'business-rule': 'rule',
    'notification': 'notifications',
    'subprocess': 'hub',
    'start': 'play-circle-rounded',
    'end': 'stop-circle',
    'swimlane-horizontal': 'view-stream',
    'swimlane-vertical': 'view-column',
    'rectangle-shape': 'rectangle',
    'text-annotation': 'text-fields',
    'process-group': 'group-work'
  };
  return iconMap[nodeType] || 'account_tree';
};

// Helper function to validate and normalize hex color
const normalizeHexColor = (value, fallback = '#ffffff') => {
  if (!value || typeof value !== 'string') return fallback;
  
  // Remove # if present and trim whitespace
  let hex = value.toString().replace('#', '').trim();
  
  // If empty after processing, return fallback
  if (!hex) return fallback;
  
  // If it's a 3-character hex, expand it to 6
  if (hex.length === 3 && /^[0-9a-fA-F]{3}$/.test(hex)) {
    hex = hex.split('').map(char => char + char).join('');
  }
  
  // Validate hex format (6 characters, valid hex digits)
  if (!/^[0-9a-fA-F]{6}$/.test(hex)) {
    // Return fallback color if invalid
    console.warn(`Invalid hex color: ${value}, using fallback: ${fallback}`);
    return fallback;
  }
  
  return `#${hex.toLowerCase()}`;
};

// Add computed properties for node colors
const nodeBackgroundColor = computed({
  get: () => {
    if (!selectedNodeData.value?.data) return '#ffffff';
    const color = selectedNodeData.value.data.backgroundColor || '#ffffff';
    return normalizeHexColor(color, '#ffffff');
  },
  set: (value) => {
    if (selectedNodeData.value) {
      const normalizedColor = normalizeHexColor(value, '#ffffff');
      selectedNodeData.value.data.backgroundColor = normalizedColor;
      updateNodeInStore();
    }
  }
});

const nodeBorderColor = computed({
  get: () => {
    if (!selectedNodeData.value?.data) return '#dddddd';
    const color = selectedNodeData.value.data.borderColor || '#dddddd';
    return normalizeHexColor(color, '#dddddd');
  },
  set: (value) => {
    if (selectedNodeData.value) {
      const normalizedColor = normalizeHexColor(value, '#dddddd');
      selectedNodeData.value.data.borderColor = normalizedColor;
      updateNodeInStore();
    }
  }
});

const nodeTextColor = computed({
  get: () => {
    if (!selectedNodeData.value?.data) return '#333333';
    const color = selectedNodeData.value.data.textColor || '#333333';
    return normalizeHexColor(color, '#333333');
  },
  set: (value) => {
    if (selectedNodeData.value) {
      const normalizedColor = normalizeHexColor(value, '#333333');
      selectedNodeData.value.data.textColor = normalizedColor;
      updateNodeInStore();
    }
  }
});

// Add validation function for color inputs
const validateColorInput = (event) => {
  const input = event.target;
  const value = input.value;
  
  // Remove invalid class first
  input.classList.remove('border-red-500');
  
  // If empty, that's ok (will use default)
  if (!value.trim()) {
    return;
  }
  
  // Check if valid hex color
  const hex = value.replace('#', '').trim();
  const isValid = /^[0-9a-fA-F]{3}$/.test(hex) || /^[0-9a-fA-F]{6}$/.test(hex);
  
  if (!isValid) {
    input.classList.add('border-red-500');
  }
};

// Add a computed property for gateway conditions
const nodeConditions = computed({
  get: () => selectedNodeData.value?.data?.conditions || [],
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.conditions = value;
      updateNodeInStore();
    }
  }
});

// Add a computed property for gateway default path
const nodeDefaultPath = computed({
  get: () => selectedNodeData.value?.data?.defaultPath || 'Default',
  set: (value) => {
    if (selectedNodeData.value) {
      selectedNodeData.value.data.defaultPath = value;
      updateNodeInStore();
    }
  }
});

// Computed for gateway available variables
const gatewayAvailableVariables = computed(() => {
  if (!processStore.currentProcess || !processStore.currentProcess.variables) {
    return [];
  }
  
  // Get variables from the current process instead of variable store
  const processVariables = Object.values(processStore.currentProcess.variables);
  
  const allVars = processVariables.map(v => ({
    name: v.name || 'unnamed',
    label: `${v.name || 'unnamed'} (${v.type || 'string'})`,
    type: v.type || 'string',
    scope: v.scope || 'global',
    description: v.description || ''
  }));
  
  return allVars;
});

// Computed key that changes when variables are updated to force re-render of configuration modals
const variablesUpdateKey = computed(() => {
  if (!processStore.currentProcess || !processStore.currentProcess.variables) {
    return 'no-variables';
  }
  
  // Create a hash of variable names to detect changes
  const variableNames = Object.keys(processStore.currentProcess.variables).sort().join(',');
  return `vars-${variableNames.length}-${variableNames.split('').reduce((a, b) => {
    a = ((a << 5) - a) + b.charCodeAt(0);
    return a & a;
  }, 0)}`;
});

// Handle node selection
const onNodeSelected = (node) => {
  // console.log('Node selected:', node);
  
  // Create a deep copy of the node to avoid reactivity issues
  const nodeCopy = JSON.parse(JSON.stringify(node));
  
  // Always ensure label is present in both places for consistency
  if (!nodeCopy.label && nodeCopy.data && nodeCopy.data.label) {
    // If label is missing but exists in data, use it
    nodeCopy.label = nodeCopy.data.label;
  } else if (nodeCopy.label && nodeCopy.data) {
    // If label exists, make sure it's also in data
    nodeCopy.data.label = nodeCopy.label;
  }
  
  // Set the selected node data first to avoid causing canvas to disappear
  selectedNodeData.value = nodeCopy;
  selectedNode.value = node;
  selectedEdgeData.value = null;
  processStore.selectNode(node.id);
  
  // Then handle defaults asynchronously to avoid disrupting the canvas
  if (nodeCopy.data && nodeCopy.type !== 'start' && nodeCopy.type !== 'end') {
    let shouldUpdate = false;
    
    // Set default shape
    if (!nodeCopy.data.shape) {
      let defaultShape = 'rectangle';
      if (nodeCopy.type === 'gateway') {
        defaultShape = 'diamond';
      }
      nodeCopy.data.shape = defaultShape;
      shouldUpdate = true;
    }
    
    // Set default colors based on node type
    if (!nodeCopy.data.backgroundColor || !nodeCopy.data.borderColor || !nodeCopy.data.textColor) {
      let defaultColors = { backgroundColor: '#ffffff', borderColor: '#dddddd', textColor: '#333333' };
      
      switch (nodeCopy.type) {
        case 'form':
          defaultColors = { backgroundColor: '#faf5ff', borderColor: '#9333ea', textColor: '#6b21a8' };
          break;
        case 'api':
          defaultColors = { backgroundColor: '#eff6ff', borderColor: '#3b82f6', textColor: '#1e40af' };
          break;
        case 'gateway':
          defaultColors = { backgroundColor: '#fff7ed', borderColor: '#f97316', textColor: '#c2410c' };
          break;
        case 'script':
          defaultColors = { backgroundColor: '#f9fafb', borderColor: '#6b7280', textColor: '#374151' };
          break;
        case 'business-rule':
          defaultColors = { backgroundColor: '#fdf4ff', borderColor: '#a855f7', textColor: '#7c3aed' };
          break;
        case 'notification':
          defaultColors = { backgroundColor: '#f0f9ff', borderColor: '#0ea5e9', textColor: '#0284c7' };
          break;
        case 'subprocess':
          defaultColors = { backgroundColor: '#f0fdfa', borderColor: '#14b8a6', textColor: '#134e4a' };
          break;
      }
      
      if (!nodeCopy.data.backgroundColor) {
        nodeCopy.data.backgroundColor = defaultColors.backgroundColor;
        selectedNodeData.value.data.backgroundColor = defaultColors.backgroundColor;
        shouldUpdate = true;
      }
      
      if (!nodeCopy.data.borderColor) {
        nodeCopy.data.borderColor = defaultColors.borderColor;
        selectedNodeData.value.data.borderColor = defaultColors.borderColor;
        shouldUpdate = true;
      }
      
      if (!nodeCopy.data.textColor) {
        nodeCopy.data.textColor = defaultColors.textColor;
        selectedNodeData.value.data.textColor = defaultColors.textColor;
        shouldUpdate = true;
      }
    }
    
    // Update the original node in store asynchronously if any properties were added
    if (shouldUpdate) {
      nextTick(() => {
        processStore.updateNode(nodeCopy.id, { 
          data: { ...nodeCopy.data } 
        });
      });
    }
  }
};

// Handle edge selection
const onEdgeSelected = (edge) => {
  selectedEdgeData.value = edge;
  selectedNode.value = null;
  selectedNodeData.value = null;
  processStore.selectEdge(edge.id);
};

// Update edge label
const updateEdgeLabel = (value) => {
  if (selectedEdgeData.value) {
    processStore.updateEdge(selectedEdgeData.value.id, { label: value });
    selectedEdgeData.value.label = value;
  }
};

// Update the pane click handler to clear edge selection too
const onPaneClick = () => {
  onPaneClickMobile();
};

// Enhanced updateNodeInStore with automatic refresh and canvas sync
const updateNodeInStore = async () => {
  if (selectedNodeData.value) {
    const nodeId = selectedNodeData.value.id;
    const newLabel = selectedNodeData.value.label;
    const newData = { ...selectedNodeData.value.data };
    
    // Update in store first
    processStore.updateNode(nodeId, {
      label: newLabel,
      data: newData
    });
    
    // Wait for store update to complete
    await nextTick();
    
    // Force canvas update directly for immediate feedback
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      // Include z-index in style if this is a shape
      const isShape = newData?.isShape || false;
      const style = isShape ? { zIndex: newData.zIndex ?? 0 } : {};
      
      processFlowCanvas.value.updateNode(nodeId, {
        label: newLabel,
        data: newData,
        style: style
      });
    }
    
    // Refresh selected node from store to maintain consistency
    refreshSelectedNodeFromStore();
  }
};

// Enhanced refresh function with change detection to prevent loops
const refreshSelectedNodeFromStore = () => {
  if (selectedNodeData.value && processStore.currentProcess) {
    const storeNode = processStore.currentProcess.nodes.find(node => node.id === selectedNodeData.value.id);
    if (storeNode) {
      // Use a more sophisticated comparison to detect actual changes
      const hasChanges = (
        selectedNodeData.value.label !== storeNode.label ||
        JSON.stringify(selectedNodeData.value.data) !== JSON.stringify(storeNode.data) ||
        selectedNodeData.value.position?.x !== storeNode.position?.x ||
        selectedNodeData.value.position?.y !== storeNode.position?.y
      );
      
      if (hasChanges) {
        selectedNodeData.value = { ...storeNode, data: { ...storeNode.data } };
      }
    }
  }
};

// Special handler for shape size updates to force reactivity
const updateShapeSize = async () => {
  if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
    // Get the z-index before updating
    const zIndex = selectedNodeData.value.data.zIndex || 0;
    
    // Force update the node in store with new size
    updateNodeInStore();
    
    // Also force update the canvas to ensure immediate visual feedback
    await nextTick();
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
        data: { ...selectedNodeData.value.data },
        style: { zIndex }
      });
      
      // Also directly manipulate DOM for immediate feedback
      const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
      if (nodeElement) {
        nodeElement.style.zIndex = zIndex;
        
        // Also update custom-node if it exists
        const customNode = nodeElement.querySelector('.custom-node');
        if (customNode) {
          customNode.style.zIndex = zIndex;
        }
      }
    }
  }
};

// Reset node colors to default based on node type
const resetNodeColors = () => {
  if (selectedNodeData.value) {
    const nodeType = selectedNodeData.value.type;
    let defaultColors = { backgroundColor: '#ffffff', borderColor: '#dddddd', textColor: '#333333' };
    
    // Set type-specific default colors
    switch (nodeType) {
      case 'form':
        defaultColors = { backgroundColor: '#faf5ff', borderColor: '#9333ea', textColor: '#6b21a8' };
        break;
      case 'api':
        defaultColors = { backgroundColor: '#eff6ff', borderColor: '#3b82f6', textColor: '#1e40af' };
        break;
      case 'gateway':
        defaultColors = { backgroundColor: '#fff7ed', borderColor: '#f97316', textColor: '#c2410c' };
        break;
      case 'script':
        defaultColors = { backgroundColor: '#f9fafb', borderColor: '#6b7280', textColor: '#374151' };
        break;
      case 'business-rule':
        defaultColors = { backgroundColor: '#fdf4ff', borderColor: '#a855f7', textColor: '#7c3aed' };
        break;
      case 'notification':
        defaultColors = { backgroundColor: '#f0f9ff', borderColor: '#0ea5e9', textColor: '#0284c7' };
        break;
      case 'subprocess':
        defaultColors = { backgroundColor: '#f0fdfa', borderColor: '#14b8a6', textColor: '#134e4a' };
        break;
    }
    
    selectedNodeData.value.data.backgroundColor = defaultColors.backgroundColor;
    selectedNodeData.value.data.borderColor = defaultColors.borderColor;
    selectedNodeData.value.data.textColor = defaultColors.textColor;
    updateNodeInStore();
  }
};

// Handle condition update
const handleConditionUpdate = async (conditions) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'gateway') {
    // Update conditions in the node data
    selectedNodeData.value.data = {
      ...selectedNodeData.value.data,
      conditions: conditions
    };
    
    // Update edges with new condition outputs
    if (processStore.currentProcess?.edges) {
      const updatedEdges = processStore.currentProcess.edges.map(edge => {
        if (edge.source === selectedNodeData.value.id) {
          // Find matching condition group
          const matchingGroup = conditions.find(group => group.output === edge.label);
          
          // If no matching group found, and this isn't the default path, update edge label
          if (!matchingGroup && edge.label !== selectedNodeData.value.data.defaultPath) {
            return {
              ...edge,
              label: selectedNodeData.value.data.defaultPath || 'Default'
            };
          }
        }
        return edge;
      });
      
      // Update edges in store
      processStore.currentProcess.edges = updatedEdges;
    }
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Handle updates from the canvas when nodes change
const onNodesChange = (changes, currentNodes) => {
  if (!changes || !currentNodes) return;
  
  // Handle position changes FIRST (always allow position updates)
  // This ensures user drag operations are saved to store
  const positionChanges = {};
  const positionChangesList = changes
    .filter(change => change.type === 'position' && change.position && !change.dragging);
    
  positionChangesList.forEach(change => {
    positionChanges[change.id] = change.position;
  });
    
  if (Object.keys(positionChanges).length > 0) {
    console.log('📍 User moved nodes - updating store:', Object.keys(positionChanges));
    processStore.updateNodePositions(positionChanges);
  }
  
  // Skip other processing during component addition to avoid conflicts
  // But ALWAYS allow position updates above
  if (isAddingComponent.value) {
    console.log('🚫 Skipping other node changes during component addition');
    return;
  }
  
  // Handle node removals (from delete key or other removal actions)
  const removedNodes = changes
    .filter(change => change.type === 'remove')
    .map(change => change.id);
    
  if (removedNodes.length > 0) {
    removedNodes.forEach(nodeId => {
      processStore.deleteNode(nodeId);
    });
    
    // Clear selection if the selected node was deleted
    if (selectedNodeData.value && removedNodes.includes(selectedNodeData.value.id)) {
      selectedNodeData.value = null;
    }
  }
  
  // FIXED: Handle node additions from canvas drops (drag and drop from component panel)
  const addedNodes = changes.filter(change => change.type === 'add');
    
  if (addedNodes.length > 0) {
    addedNodes.forEach(async (change) => {
      // Check if this node came from a canvas drop event (has item property)
      if (change.item) {
        console.log('📦 Parent: Received drop event for node:', change.item.id);
        
        // Set flag to prevent interference
        isAddingComponent.value = true;
        
        try {
          // Add the node to store only (canvas already has it from the drop)
          const addedNode = await processStore.addNode(change.item);
          
          if (addedNode) {
            // Select the newly added node
            onNodeSelected(addedNode);
            console.log('✅ Parent: Successfully added dropped node to store:', addedNode.id);
          }
        } catch (error) {
          console.error('❌ Parent: Error adding dropped node to store:', error);
        } finally {
          // Reset flag after a delay to ensure stability
          setTimeout(() => {
            isAddingComponent.value = false;
          }, 200);
        }
      }
    });
  }
  
  // REMOVED: Don't overwrite selectedNodeData from canvas changes to preserve local edits
  // This was causing property panel changes to be lost when the canvas updated
  // The canvasNodes computed and its watcher will handle synchronization properly
};

// Handle updates from the canvas when edges change
const onEdgesChange = (changes, currentEdges) => {
  if (!changes || !currentEdges) return;
  
  // Skip processing during component addition to avoid conflicts
  if (isAddingComponent.value) {
    return;
  }
  
  // Handle edge removals
  const removedEdges = changes
    .filter(change => change.type === 'remove')
    .map(change => change.id);
    
  if (removedEdges.length > 0) {
    removedEdges.forEach(edgeId => {
      processStore.deleteEdge(edgeId);
    });
    
    // Clear selection if the selected edge was deleted
    if (selectedEdgeData.value && removedEdges.includes(selectedEdgeData.value.id)) {
      selectedEdgeData.value = null;
    }
  }
  
  // Handle edge additions (new connections)
  const addedEdges = changes.filter(change => change.type === 'add');
  
  if (addedEdges.length > 0) {
    addedEdges.forEach(change => {
      const edge = currentEdges.find(e => e.id === change.id);
      if (edge) {
        processStore.addEdge({
          id: edge.id,
          source: edge.source,
          target: edge.target,
          label: edge.label || '',
          type: edge.type || 'custom',
          animated: edge.animated !== undefined ? edge.animated : true,
          data: edge.data || {},
          sourceHandle: edge.sourceHandle,
          targetHandle: edge.targetHandle
        });
      }
    });
  }
};

// Handle creating a new process
const createNewProcess = async () => {
  if (!newProcessName.value.trim()) {
    toast.error('Please enter a process name');
    return;
  }
  
  try {
    const newProcess = await processStore.createProcess(
      newProcessName.value.trim(),
      newProcessDescription.value.trim()
    );
    
    if (newProcess && newProcess.id) {
      // Update the URL to include the new process ID
      router.replace(`/process-builder?id=${newProcess.id}`);
      
      // Show success message
      toast.success(`Process "${newProcess.name}" created successfully`);
      
      // Reset form
      isCreatingProcess.value = false;
      newProcessName.value = '';
      newProcessDescription.value = '';
      
      // Reset navigation confirmation
      navigationConfirmed.value = false;
    } else {
      toast.error('Failed to create process. Please try again.');
    }
  } catch (error) {
    console.error('Error creating process:', error);
    toast.error(`Failed to create process: ${error.message || 'Unknown error'}`);
  }
};

// Add navigation guard
onBeforeRouteLeave((to, from, next) => {
  // If navigation was already confirmed or there are no unsaved changes, proceed
  if (navigationConfirmed.value || !processStore.hasUnsavedChanges) {
    next();
    return;
  }
  
  // Otherwise show the confirmation modal
  showUnsavedChangesModal.value = true;
  pendingNavigation.value = () => {
    navigationConfirmed.value = true;
    next();
  };
  next(false);
});

// Navigation handlers
const cancelNavigation = () => {
  showUnsavedChangesModal.value = false;
  pendingNavigation.value = null;
  navigationTarget.value = null;
  navigationConfirmed.value = false;
};

// Update the confirmNavigation function to handle targets
const confirmNavigation = (target) => {
  // Force check unsaved changes by calling the getter
  const hasChanges = processStore.hasUnsavedChanges;
  
  // If already confirmed or no unsaved changes, navigate directly
  if (navigationConfirmed.value || !hasChanges) {
    // Clear the current process when navigating away
    if (target !== '/process-builder') {
      processStore.clearCurrentProcess();
    }
    // Reset navigation confirmation
    navigationConfirmed.value = false;
    router.push(target);
    return;
  }
  
  // Otherwise show confirmation modal
  showUnsavedChangesModal.value = true;
  navigationTarget.value = target;
};

// Add proceeding with navigation
const proceedWithNavigation = () => {
  showUnsavedChangesModal.value = false;
  
  if (pendingNavigation.value) {
    pendingNavigation.value();
  } else if (navigationTarget.value) {
    // Clear the current process when navigating away
    if (navigationTarget.value !== '/process-builder') {
      processStore.clearCurrentProcess();
    }
    navigationConfirmed.value = true; // Mark as confirmed before navigating
    router.push(navigationTarget.value);
  }
};

// Update the goToManage function to use the navigation system
const goToManage = () => {
  // If already confirmed or no unsaved changes, navigate directly
  if (navigationConfirmed.value || !processStore.hasUnsavedChanges) {
    router.push('/process-builder/manage');
    return;
  }
  
  // Otherwise show confirmation modal
  showUnsavedChangesModal.value = true;
  navigationTarget.value = "/process-builder/manage";
};



// Add events for beforeunload
onMounted(() => {
  // Load clipboard from localStorage
  loadClipboardFromStorage();
  
  // Check if there's a process ID in the URL query parameters
  const processId = route.query.id;
  
  if (processId) {
    // Load the specific process
    processStore.loadProcess(processId).then((result) => {
      if (!result.success) {
        console.error('Failed to load process:', processId, result.error);
        // Could show an error notification here
        // For now, just redirect back to manage page
        router.push('/process-builder/manage');
      }
    }).catch((error) => {
      console.error('Error loading process:', error);
      router.push('/process-builder/manage');
    });
  }
  
  // Add the beforeunload event listener
  window.addEventListener('beforeunload', handleBeforeUnload);
  
  // Add click outside listener for dropdown
  document.addEventListener('click', handleClickOutside);
  
  // Add resize listener for responsive behavior
  window.addEventListener('resize', checkScreenSize);
  
  // Add node highlight listener for variable navigation
  window.addEventListener('highlightNode', handleNodeHighlight);
  
  // Add keyboard shortcuts listener
  window.addEventListener('keydown', handleKeyboardShortcuts);
  
  // Add storage event listener for cross-tab clipboard sync
  window.addEventListener('storage', handleStorageEvent);
  
  // Initial screen size check
  checkScreenSize();
});

// Handle click outside dropdown
const handleClickOutside = (event) => {
  if (!event.target.closest('.dropdown')) {
    showDropdown.value = false;
  }
};

onUnmounted(() => {
  // Remove event listeners
  window.removeEventListener('beforeunload', handleBeforeUnload);
  document.removeEventListener('click', handleClickOutside);
  window.removeEventListener('resize', checkScreenSize);
  window.removeEventListener('highlightNode', handleNodeHighlight);
  window.removeEventListener('keydown', handleKeyboardShortcuts);
  window.removeEventListener('storage', handleStorageEvent);
  
  // Clear highlight timeout if it exists
  if (highlightTimeout.value) {
    clearTimeout(highlightTimeout.value);
  }
});

// Show warning if there are unsaved changes
const handleBeforeUnload = (event) => {
  if (processStore.hasUnsavedChanges) {
    event.preventDefault();
    event.returnValue = '';
    return '';
  }
};

// Handle drag start
const onDragStart = (event, component) => {
  try {
    const dragData = {
      type: component.type,
      label: component.label,
      data: {
        ...component.data,
        label: component.label
      }
    };
    
    draggedComponent.value = dragData;
    event.dataTransfer.effectAllowed = 'move';
    event.dataTransfer.setData('application/json', JSON.stringify(dragData));
    
    // Add visual feedback
    event.target.classList.add('dragging');
  } catch (error) {
    console.error('Error starting drag:', error);
  }
};

// Handle drag end
const onDragEnd = (event) => {
  event.target.classList.remove('dragging');
  draggedComponent.value = null;
};

// Add these functions to handle form selection
const handleFormSelection = (form) => {
  if (selectedNodeData.value) {
    // Update all form-related data
    selectedNodeData.value.data = {
      ...selectedNodeData.value.data,
      formId: form.formID,
      formName: form.formName,
      formUuid: form.formUUID,
      label: form.formName,
      description: `Form: ${form.formName}`
    };
    
    // Also update the node's root label
    selectedNodeData.value.label = form.formName;
    
    // Update the node in store to trigger reactivity
    updateNodeInStore();
  }
};

const clearFormSelection = () => {
  if (selectedNodeData.value) {
    selectedNodeData.value.data = {
      ...selectedNodeData.value.data,
      formId: null,
      formName: '',
      formUuid: null,
      label: 'Form Task',
      description: 'Form submission task'
    };
    
    // Reset the node's root label
    selectedNodeData.value.label = 'Form Task';
    
    // Update the node in store
    updateNodeInStore();
  }
};

// Delete current node
const deleteNode = () => {
  if (selectedNodeData.value) {
    // Store the node ID before clearing the selection
    const nodeId = selectedNodeData.value.id;
    
    // Clear selection first to avoid references to deleted node
    selectedNodeData.value = null;
    selectedNode.value = null;
    
    // Delete the node
    processStore.deleteNode(nodeId);
  }
};

// Delete current edge
const deleteEdge = () => {
  if (selectedEdgeData.value) {
    processStore.deleteEdge(selectedEdgeData.value.id);
    selectedEdgeData.value = null;
  }
};

// Save current process
const saveProcess = async () => {
  if (!processStore.currentProcess) {
    toast.error('No process to save');
    return;
  }
  
  if (!processStore.currentProcess.name.trim()) {
    toast.error('Please enter a process name before saving');
    return;
  }
  
  if (isSaving.value) {
    return; // Prevent multiple simultaneous save operations
  }
  
  try {
    isSaving.value = true;
    
    // Capture complete Vue Flow state before saving
    if (processFlowCanvas.value && processFlowCanvas.value.toObject) {
          try {
      const flowState = processFlowCanvas.value.toObject();
      
      if (flowState && flowState.nodes) {
        // Set the captured flow state in the store for saving
        processStore.setFlowStateForSave(flowState);
        } else {
          console.warn('⚠️ Vue Flow state capture returned invalid data, proceeding with store data');
        }
      } catch (captureError) {
        console.error('❌ Error capturing Vue Flow state:', captureError);
        console.warn('⚠️ Proceeding with store data as fallback');
      }
    } else {
      console.warn('⚠️ Vue Flow canvas not available for state capture');
    }
    
    const success = await processStore.saveProcess();
    
    if (success) {
      toast.success(`Process "${processStore.currentProcess.name}" saved successfully`);
      
      // Reset navigation confirmation since changes are now saved
      navigationConfirmed.value = false;
      
      // Force a reactivity update to ensure unsavedChanges is properly reflected
      await nextTick();
    } else {
      toast.error('Failed to save process. Please try again.');
    }
  } catch (error) {
    console.error('Error saving process:', error);
    toast.error(`Failed to save process: ${error.message || 'Unknown error'}`);
  } finally {
    isSaving.value = false;
  }
};

// Add a component handler to add components from the component panel
const onAddComponent = async (component) => {
  if (isAddingComponent.value || isProcessLoading.value) return; // Prevent concurrent additions or interference with process loading
  
  try {
    isAddingComponent.value = true;
    console.log('🎯 Component Panel: Adding component:', component.type);
    
    // Create a new node from the component definition
    // The component structure from ProcessBuilderComponents is:
    // { type, label, data: { ...defaultProps.data } }
    
    // Calculate a better position for the new node to avoid overlap
    let nodePosition = { x: 100, y: 100 };
    if (processStore.currentProcess && processStore.currentProcess.nodes.length > 0) {
      // Find the rightmost and bottommost positions
      const maxX = Math.max(...processStore.currentProcess.nodes.map(n => n.position?.x || 0));
      const maxY = Math.max(...processStore.currentProcess.nodes.map(n => n.position?.y || 0));
      
      // Place new node to the right with some spacing
      nodePosition = { 
        x: maxX + 200, // 200px spacing from rightmost node
        y: Math.max(100, maxY) // At least 100px from top, or at the level of the bottommost node
      };
    }
    
    const newNode = {
      id: `${component.type}_${Date.now()}`,
      type: component.type,
      position: nodePosition,
      label: component.label,
      data: {
        ...component.data
      }
    };
    
    // If this is a shape node, set an initial z-index
    if (component.data?.isShape) {
      // Find the highest z-index among existing shapes
      let highestZ = 0;
      if (processStore.currentProcess && processStore.currentProcess.nodes) {
        processStore.currentProcess.nodes.forEach(node => {
          if (node.data?.isShape) {
            const nodeZ = parseInt(node.data.zIndex || 0, 10);
            highestZ = Math.max(highestZ, nodeZ);
          }
        });
      }
      
      // Set new shape's z-index to be on top of existing shapes
      // Add 10 to ensure it's clearly above other shapes
      const newZ = highestZ + 10;
      newNode.data.zIndex = newZ;
      
      // Add style with z-index
      newNode.style = { zIndex: newZ };
      
      // After the node is added, directly manipulate the DOM to ensure z-index is applied
      setTimeout(() => {
        const nodeElement = document.querySelector(`[data-id="${newNode.id}"]`);
        if (nodeElement) {
          nodeElement.style.zIndex = newZ;
          
          // Also update custom-node if it exists
          const customNode = nodeElement.querySelector('.custom-node');
          if (customNode) {
            customNode.style.zIndex = newZ;
          }
        }
      }, 100);
    }
    
    // UPDATED: Add to store first, canvas sync will happen automatically through watchers
    console.log('📝 Component Panel: Adding node to store:', newNode.id);
    const addedNode = await processStore.addNode(newNode);
    
    if (!addedNode) {
      console.error('❌ Component Panel: Failed to add node to store');
      toast.error('Failed to add component to store. Please try again.');
      return;
    }
    
    // Wait for store update and canvas sync through watchers
    await nextTick();
    await new Promise(resolve => setTimeout(resolve, 100));
    
    // Select the newly added node after it's stable
    onNodeSelected(addedNode);
    
    console.log('✅ Component Panel: Successfully added node:', addedNode.id, 'at position:', addedNode.position);
    
  } catch (error) {
    console.error('❌ Component Panel: Error adding component:', error);
    toast.error('Failed to add component. Please try again.');
  } finally {
    // Reset the flag after a longer delay to ensure canvas is stable
    setTimeout(() => {
      console.log('🏁 Component Panel: Addition completed, resetting flag');
      isAddingComponent.value = false;
    }, 300);
  }
};

// Handle template application
const applyProcessTemplate = async (template) => {
  try {

    
    // Create a new process if one doesn't exist
    if (!processStore.currentProcess) {

      processStore.createProcess(template.name, template.description || 'Process created from template');
    } else {
      // Confirm if there's already content in the existing process
      if (processStore.currentProcess.nodes.length > 0 || processStore.currentProcess.edges.length > 0) {
        if (!confirm("This will replace your current process content. Continue?")) {
          return;
        }
      }
      
      // Update process name if user allows
      if (processStore.currentProcess.name === 'New Process' || confirm("Update the process name to match the template?")) {
        processStore.currentProcess.name = template.name;
        processStore.currentProcess.description = template.description;
      }
    }

    // Clear current process nodes and edges
    if (processStore.currentProcess) {

      processStore.currentProcess.nodes = [];
      processStore.currentProcess.edges = [];
    }

    // Prepare template data
    const templateNodes = template.nodes || [];
    const templateEdges = template.edges || [];
    
    
    
    // Process nodes first and wait for them to be fully added
    for (const node of templateNodes) {
      // Get default styling for the node type
      const defaultStyling = getDefaultNodeStyling(node.type);
      
      const newNode = {
        ...node,
        id: node.id, // Keep original ID for edge references
        label: node.data?.label || node.label || `${node.type} node`, // Set label at root level
        position: node.position || { x: 100, y: 100 },
        data: {
          ...node.data,
          label: node.data?.label || node.label || `${node.type} node`,
          // Preserve styling properties from template or use defaults
          backgroundColor: node.data?.backgroundColor || defaultStyling.backgroundColor,
          borderColor: node.data?.borderColor || defaultStyling.borderColor,
          textColor: node.data?.textColor || defaultStyling.textColor,
          shape: node.data?.shape || defaultStyling.shape
        }
      };
      
      processStore.addNode(newNode);
    }
    
    // Wait for nodes to be processed by the canvas
    await nextTick();
    await new Promise(resolve => setTimeout(resolve, 100));
    
    // Process edges after nodes are fully loaded
    for (const edge of templateEdges) {
      const newEdge = {
        ...edge,
        id: edge.id, // Keep original ID
        type: edge.type || 'custom',
        animated: edge.animated !== undefined ? edge.animated : true
      };
      
      processStore.addEdge(newEdge);
    }
    
    // Wait for edges to be added to store
    await nextTick();
    
    // Explicitly sync the canvas to ensure everything is displayed
    if (processFlowCanvas.value && processFlowCanvas.value.syncCanvas) {

      processFlowCanvas.value.syncCanvas(
        processStore.currentProcess.nodes,
        processStore.currentProcess.edges
      );
    }
    
    // Add template variables to the variable store
    if (template.variables && template.variables.length > 0) {
      
      
      // Clear existing process variables first (they'll be loaded from the process)
      // Process variables are now managed directly in the process store
      
      template.variables.forEach((variable) => {
        
        processStore.addProcessVariable({
          ...variable,
          id: crypto.randomUUID() // Generate unique ID for the variable
        });
      });
    }

    

    // Mark the process as having unsaved changes
    processStore.unsavedChanges = true;
    
    // Fit the view to show all nodes after a short delay
    await nextTick();
    setTimeout(() => {
      if (processFlowCanvas.value && processFlowCanvas.value.fitView) {
        processFlowCanvas.value.fitView();
      }
    }, 200);
    
    // Show success message
    toast.success(`Template "${template.name}" applied successfully`);
    
  } catch (error) {
    console.error('Error applying process template:', error);
    toast.error('Failed to apply template: ' + error.message);
  }
};

// Get default styling for node types
const getDefaultNodeStyling = (nodeType) => {
  const stylingMap = {
    'start': {
      backgroundColor: '#dcfce7',
      borderColor: '#10b981',
      textColor: '#065f46',
      shape: 'circle'
    },
    'end': {
      backgroundColor: '#fee2e2',
      borderColor: '#dc2626',
      textColor: '#991b1b',
      shape: 'circle'
    },
    'form': {
      backgroundColor: '#faf5ff',
      borderColor: '#9333ea',
      textColor: '#6b21a8',
      shape: 'rectangle'
    },
    'api': {
      backgroundColor: '#eff6ff',
      borderColor: '#3b82f6',
      textColor: '#1e40af',
      shape: 'rectangle'
    },
    'gateway': {
      backgroundColor: '#fff7ed',
      borderColor: '#f97316',
      textColor: '#c2410c',
      shape: 'diamond'
    },
    'notification': {
      backgroundColor: '#f0f9ff',
      borderColor: '#0ea5e9',
      textColor: '#0284c7',
      shape: 'rectangle'
    },
    'business-rule': {
      backgroundColor: '#fdf4ff',
      borderColor: '#a855f7',
      textColor: '#7c3aed',
      shape: 'rectangle'
    },
    'script': {
      backgroundColor: '#f9fafb',
      borderColor: '#6b7280',
      textColor: '#374151',
      shape: 'rectangle'
    },
    'html': {
      backgroundColor: '#e0f2fe',
      borderColor: '#0ea5e9',
      textColor: '#0c4a6e',
      shape: 'rectangle'
    },
    'subprocess': {
      backgroundColor: '#f0fdfa',
      borderColor: '#14b8a6',
      textColor: '#134e4a',
      shape: 'rectangle'
    }
  };
  
  return stylingMap[nodeType] || {
    backgroundColor: '#ffffff',
    borderColor: '#e2e8f0',
    textColor: '#374151',
    shape: 'rectangle'
  };
};
// Fix references to functions
const onFormSelected = (formData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'form') {
    selectedNodeData.value.data.formId = formData.id;
    selectedNodeData.value.data.formName = formData.name;
    updateNodeInStore();
  }
};

const onConditionsUpdated = (conditions) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'gateway') {
    selectedNodeData.value.data.conditions = conditions;
    updateNodeInStore();
  }
};

// Handle API node update
const handleApiNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'api') {
    // Make sure to update the label both in data and at the root level
    const newLabel = updatedData.label || 'API Call';
    
    // Update the data
    selectedNodeData.value.data = {
      ...updatedData,
      label: newLabel // Ensure label is in data
    };
    
    // Also update the root label
    selectedNodeData.value.label = newLabel;
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Add this function to handle form node updates
const handleFormNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'form') {
    // Make sure to update the label both in data and at the root level
    const newLabel = updatedData.label || 'Form Task';
    
    // Update the data
    selectedNodeData.value.data = {
      ...updatedData,
      label: newLabel // Ensure label is in data
    };
    
    // Also update the root label
    selectedNodeData.value.label = newLabel;
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Update handler for business rule node
const handleBusinessRuleUpdate = async (data) => {
  if (selectedNodeData.value) {
    selectedNodeData.value.data = {
      ...selectedNodeData.value.data,
      ...data
    };
    await updateNodeInStore();
  }
};

// Add a method to handle default path updates
const handleDefaultPathUpdate = async (path) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'gateway') {
    selectedNodeData.value.data.defaultPath = path;
    await updateNodeInStore();
  }
};

// Handle notification node update
const handleNotificationNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value) {
    selectedNodeData.value.data = { ...updatedData };
    await updateNodeInStore();
  }
};

// Handle script node update
const handleScriptNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'script') {
    // Make sure to update the label both in data and at the root level
    const newLabel = updatedData.label || 'Script Task';
    
    // Update the data
    selectedNodeData.value.data = {
      ...updatedData,
      label: newLabel // Ensure label is in data
    };
    
    // Also update the root label
    selectedNodeData.value.label = newLabel;
    
    // Add output variables to the process
    if (updatedData.outputVariables && Array.isArray(updatedData.outputVariables)) {
      updatedData.outputVariables.forEach(output => {
        if (output.name && output.name.trim()) {
          processStore.addProcessVariable({
            name: output.name,
            type: output.type || 'string',
            scope: 'global',
            value: null,
            description: output.description || `Output from ${newLabel}`
          });
        }
      });
    }
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Handle HTML node update
const handleHtmlNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'html') {
    // Make sure to update the label both in data and at the root level
    const newLabel = updatedData.label || 'HTML Content';
    
    // Update the data
    selectedNodeData.value.data = {
      ...updatedData,
      label: newLabel // Ensure label is in data
    };
    
    // Also update the root label
    selectedNodeData.value.label = newLabel;
    
    // Add output variables to the process
    if (updatedData.outputVariables && Array.isArray(updatedData.outputVariables)) {
      updatedData.outputVariables.forEach(output => {
        if (output.name && output.name.trim()) {
          processStore.addProcessVariable({
            name: output.name,
            type: output.type || 'string',
            scope: 'global',
            value: null,
            description: output.description || `Output from ${newLabel}`
          });
        }
      });
    }
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Handle Sub-process node update
const handleSubprocessNodeUpdate = async (updatedData) => {
  if (selectedNodeData.value && selectedNodeData.value.type === 'subprocess') {
    // Make sure to update the label both in data and at the root level
    const newLabel = updatedData.label || 'Sub Process';
    
    // Update the data
    selectedNodeData.value.data = {
      ...updatedData,
      label: newLabel // Ensure label is in data
    };
    
    // Also update the root label
    selectedNodeData.value.label = newLabel;
    
    // Update the node in store and refresh
    await updateNodeInStore();
  }
};

// Handle process restoration from history
const handleProcessRestored = (restoredProcess) => {
  // The process has been restored in the backend, so we need to reload it
  
  // The current process will be automatically updated by the store
  toast.success('Process has been restored successfully');
};

// Handle canvas export
const handleExportCanvas = async (options) => {
  try {
    if (!processFlowCanvas.value) {
      throw new Error('Canvas not available for export');
    }

    console.log('Starting export with options:', options);

    if (options.format === 'png') {
      await processFlowCanvas.value.exportToPNG(options);
      toast.success('Canvas exported as PNG successfully');
    } else if (options.format === 'pdf') {
      await processFlowCanvas.value.exportToPDF(options);
      toast.success('Canvas exported as PDF successfully');
    }
  } catch (error) {
    console.error('Export error:', error);
    toast.error(`Export failed: ${error.message}`);
    throw error;
  }
};

// Navigate to variables page
const navigateToVariables = () => {
  confirmNavigation('/variables');
};

// Watch for route changes to handle process ID changes
watch(() => route.query.id, (newProcessId, oldProcessId) => {
  // Only react if the process ID actually changed and it's not empty
  if (newProcessId && newProcessId !== oldProcessId) {
    processStore.loadProcess(newProcessId).then((result) => {
      if (!result.success) {
        console.error('Failed to load process:', newProcessId, result.error);
        router.push('/process-builder/manage');
      }
    }).catch((error) => {
      console.error('Error loading process:', error);
      router.push('/process-builder/manage');
    });
  } else if (!newProcessId && oldProcessId) {
    // If the ID was removed from the URL, clear the current process
    processStore.clearCurrentProcess();
  }
});

// Watch for unsaved changes to reset navigation confirmation
watch(() => processStore.hasUnsavedChanges, (hasChanges) => {
  // If there are no more unsaved changes, reset navigation confirmation
  if (!hasChanges) {
    navigationConfirmed.value = false;
  }
});

// Watch for canvas nodes changes to ensure selected node stays in sync
watch(() => canvasNodes.value, (newNodes) => {
  // If we have a selected node, make sure it's kept in sync with the canvas
  if (selectedNodeData.value && newNodes.length > 0) {
    const updatedNode = newNodes.find(node => node.id === selectedNodeData.value.id);
    if (updatedNode) {
      // Use the same change detection logic as refreshSelectedNodeFromStore
      const hasChanges = (
        selectedNodeData.value.label !== updatedNode.label ||
        JSON.stringify(selectedNodeData.value.data) !== JSON.stringify(updatedNode.data) ||
        selectedNodeData.value.position?.x !== updatedNode.position?.x ||
        selectedNodeData.value.position?.y !== updatedNode.position?.y
      );
      
      if (hasChanges) {
        selectedNodeData.value = { ...updatedNode, data: { ...updatedNode.data } };
      }
    }
  }
}, { deep: true });

// Track if we're in the middle of adding a component to prevent interference
const isProcessLoading = ref(false);

// Watch for process changes to restore Vue Flow state
// Only trigger when the entire process object changes (different process loaded)
watch(() => processStore.currentProcess?.id, async (newProcessId, oldProcessId) => {
  if (!newProcessId) return;
  
  // Only restore when a different process is loaded (not on updates to the same process)
  if (oldProcessId && newProcessId === oldProcessId) return;
  
  // Don't interfere if we're in the middle of adding a component or modifying nodes
  if (isAddingComponent.value || processStore.isModifyingNodes) {
    console.log('🚫 Skipping process restoration during component/node modification');
    return;
  }
  
  const newProcess = processStore.currentProcess;
  console.log('🔄 Loading process:', newProcessId, 'Nodes:', newProcess.nodes?.length || 0);
  isProcessLoading.value = true;
  
  // Wait for the canvas to be ready
  await nextTick();
  
  // Give the canvas component a moment to initialize
  setTimeout(async () => {
    try {
      if (processFlowCanvas.value && processFlowCanvas.value.fromObject) {
        try {
          // Prepare the flow object for restoration
          const rawFlowObject = {
            nodes: newProcess.nodes || [],
            edges: newProcess.edges || [],
            viewport: newProcess.viewport || { x: 0, y: 0, zoom: 1 }
          };
          
          // Clean the data to remove any Vue Flow internal properties
          const flowObject = processStore.cleanFlowData(rawFlowObject);
          
          console.log('🔄 Restoring Vue Flow state with', flowObject.nodes.length, 'nodes');
          
          // Use Vue Flow's proper restoration method (now returns a Promise)
          await processFlowCanvas.value.fromObject(flowObject);
          
          console.log('✅ Vue Flow state restored successfully');
          
          // Only fit view if nodes don't have meaningful positions (all at 0,0)
          // This prevents repositioning nodes that were carefully positioned
          const hasPositionedNodes = flowObject.nodes.some(node => 
            node.position && (node.position.x !== 0 || node.position.y !== 0)
          );
          
          if (!hasPositionedNodes && flowObject.nodes.length > 0) {
            setTimeout(() => {
              if (processFlowCanvas.value && processFlowCanvas.value.fitView) {
                processFlowCanvas.value.fitView();
              }
            }, 300);
          }
          
        } catch (error) {
          console.error('❌ Error restoring Vue Flow state:', error);
          
          // Fallback to manual sync if Vue Flow restoration fails
          if (processFlowCanvas.value && processFlowCanvas.value.syncCanvas) {
            console.log('🔄 Falling back to manual sync');
            processFlowCanvas.value.syncCanvas(newProcess.nodes, newProcess.edges);
          }
        }
      } else {
        console.warn('⚠️ Vue Flow canvas not available for restoration, using sync fallback');
        
        // Fallback sync method
        if (processFlowCanvas.value && processFlowCanvas.value.syncCanvas) {
          processFlowCanvas.value.syncCanvas(newProcess.nodes, newProcess.edges);
        }
      }
    } finally {
      isProcessLoading.value = false;
    }
  }, 200); // Allow time for canvas to initialize
}, { immediate: false });

// Duplicate Node logic
const duplicateNode = async () => {
  if (!selectedNodeData.value) return;
  const node = selectedNodeData.value;
  // Prevent duplication for start/end nodes and shapes
  if (node.type === 'start' || node.type === 'end' || node.data?.isShape) return;

  // Deep copy node
  const newNode = JSON.parse(JSON.stringify(node));
  newNode.id = `${node.type}_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
  // Offset position
  newNode.position = {
    x: (node.position?.x || 100) + 40,
    y: (node.position?.y || 100) + 40
  };
  // Update label
  if (newNode.label) {
    newNode.label = newNode.label.endsWith(' (Copy)') ? newNode.label : `${newNode.label} (Copy)`;
  }
  if (newNode.data && newNode.data.label) {
    newNode.data.label = newNode.data.label.endsWith(' (Copy)') ? newNode.data.label : `${newNode.data.label} (Copy)`;
  }
  // Remove any edge/connection-specific data if present
  delete newNode.selected;
  delete newNode.dragging;

  // Add to store only
  await processStore.addNode(newNode);
  await nextTick();
  // Select the new node from the store
  const freshNode = processStore.currentProcess?.nodes.find(n => n.id === newNode.id);
  if (freshNode) {
    onNodeSelected(freshNode);
  }
};

// Add computed property for action visibility
const canShowNodeActions = computed(() => {
  return (
    selectedNodeData.value &&
    selectedNodeData.value.type !== 'start' &&
    selectedNodeData.value.type !== 'end'
  );
});

// Add computed properties for copy/paste functionality
const canCopy = computed(() => {
  // Check for multiple selections first
  if (processFlowCanvas.value) {
    try {
      let selectedNodes = [];
      let selectedEdges = [];
      
      // Try the new getSelectedElements method first
      if (processFlowCanvas.value.getSelectedElements) {
        const selection = processFlowCanvas.value.getSelectedElements();
        selectedNodes = selection.nodes || [];
        selectedEdges = selection.edges || [];
      }
      
      // If no selection found, try direct access
      if (selectedNodes.length === 0 && selectedEdges.length === 0) {
        if (processFlowCanvas.value.nodes && processFlowCanvas.value.edges) {
          selectedNodes = processFlowCanvas.value.nodes.filter(node => node.selected);
          selectedEdges = processFlowCanvas.value.edges.filter(edge => edge.selected);
        }
      }
      
      // If there are multiple selections, any selection is copyable
      if (selectedNodes.length > 0 || selectedEdges.length > 0) {
        return true;
      }
    } catch (error) {
      console.warn('Failed to check multiple selections:', error);
    }
  }
  
  // Fall back to single selection check
  // Can copy edges
  if (selectedEdgeData.value) return true;
  
  // Can copy any nodes (including start/end)
  if (selectedNodeData.value) {
    return true;
  }
  
  return false;
});

const canPaste = computed(() => {
  return clipboard.value.type && processStore.currentProcess;
});

const clipboardInfo = computed(() => {
  if (!clipboard.value.type) return null;
  
  const nodeCount = clipboard.value.nodes.length;
  const edgeCount = clipboard.value.edges.length;
  
  if (clipboard.value.type === 'mixed') {
    return `${nodeCount} node${nodeCount > 1 ? 's' : ''}, ${edgeCount} edge${edgeCount > 1 ? 's' : ''}`;
  } else if (clipboard.value.type === 'nodes') {
    return `${nodeCount} node${nodeCount > 1 ? 's' : ''}`;
  } else if (clipboard.value.type === 'edges') {
    return `${edgeCount} edge${edgeCount > 1 ? 's' : ''}`;
  }
  
  return null;
});

// Add computed property to show current selection info
const currentSelectionInfo = computed(() => {
  if (!processFlowCanvas.value || !processFlowCanvas.value.flowInstance) return null;
  
  try {
    let selectedNodes = [];
    let selectedEdges = [];
    
    // Try the new getSelectedElements method first
    if (processFlowCanvas.value.getSelectedElements) {
      const selection = processFlowCanvas.value.getSelectedElements();
      selectedNodes = selection.nodes || [];
      selectedEdges = selection.edges || [];
    }
    
    // If no selection found, try direct access
    if (selectedNodes.length === 0 && selectedEdges.length === 0) {
      if (processFlowCanvas.value.nodes && processFlowCanvas.value.edges) {
        selectedNodes = processFlowCanvas.value.nodes.filter(node => node.selected);
        selectedEdges = processFlowCanvas.value.edges.filter(edge => edge.selected);
      }
    }
    
    if (selectedNodes.length === 0 && selectedEdges.length === 0) return null;
    
    let info = '';
    if (selectedNodes.length > 0) {
      info += `${selectedNodes.length} node${selectedNodes.length > 1 ? 's' : ''}`;
    }
    if (selectedEdges.length > 0) {
      if (info) info += ', ';
      info += `${selectedEdges.length} edge${selectedEdges.length > 1 ? 's' : ''}`;
    }
    
    return info;
  } catch (error) {
    console.warn('Failed to get current selection info:', error);
    return null;
  }
});

const nodeZIndex = computed({
  get: () => {
    return selectedNodeData.value?.data?.isShape ? selectedNodeData.value.data.zIndex || 0 : 0;
  },
  set: (value) => {
    if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
      const z = parseInt(value, 10);
      const newZ = isNaN(z) ? 0 : z;
      selectedNodeData.value.data.zIndex = newZ;
      updateNodeInStore();
      
      // Force update the node style in the canvas
      if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
        processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
          style: { zIndex: newZ }
        });
        
        // Also directly manipulate DOM for immediate feedback
        nextTick(() => {
          const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
          if (nodeElement) {
            nodeElement.style.zIndex = newZ;
            
            // Also update custom-node if it exists
            const customNode = nodeElement.querySelector('.custom-node');
            if (customNode) {
              customNode.style.zIndex = newZ;
            }
          }
        });
      }
    }
  }
});

// Add functions to bring forward and send backward shapes
const bringForward = () => {
  if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
    // Increment z-index by 1
    const currentZ = parseInt(selectedNodeData.value.data.zIndex || 0, 10);
    const newZ = currentZ + 1;
    selectedNodeData.value.data.zIndex = newZ;
    
    // Update in store
    updateNodeInStore();
    
    // Force update the node style in the canvas
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
        style: { zIndex: newZ }
      });
      
      // Also directly manipulate DOM for immediate feedback
      nextTick(() => {
        const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
        if (nodeElement) {
          nodeElement.style.zIndex = newZ;
          
          // Also update custom-node if it exists
          const customNode = nodeElement.querySelector('.custom-node');
          if (customNode) {
            customNode.style.zIndex = newZ;
          }
        }
      });
    }
  }
};

const sendBackward = () => {
  if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
    // Decrement z-index by 1, but not below 0
    const currentZ = parseInt(selectedNodeData.value.data.zIndex || 0, 10);
    const newZ = Math.max(0, currentZ - 1);
    selectedNodeData.value.data.zIndex = newZ;
    
    // Update in store
    updateNodeInStore();
    
    // Force update the node style in the canvas
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
        style: { zIndex: newZ }
      });
      
      // Also directly manipulate DOM for immediate feedback
      nextTick(() => {
        const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
        if (nodeElement) {
          nodeElement.style.zIndex = newZ;
          
          // Also update custom-node if it exists
          const customNode = nodeElement.querySelector('.custom-node');
          if (customNode) {
            customNode.style.zIndex = newZ;
          }
        }
      });
    }
  }
};

const bringToFront = () => {
  if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
    // Find the highest z-index in the current shapes
    let highestZ = 0;
    if (processStore.currentProcess && processStore.currentProcess.nodes) {
      processStore.currentProcess.nodes.forEach(node => {
        if (node.data?.isShape) {
          const nodeZ = parseInt(node.data.zIndex || 0, 10);
          highestZ = Math.max(highestZ, nodeZ);
        }
      });
    }
    
    // Set to higher than the highest found (add 10 to ensure it's clearly on top)
    const newZ = highestZ + 10;
    selectedNodeData.value.data.zIndex = newZ;
    
    // Update in store
    updateNodeInStore();
    
    // Force update the node style in the canvas
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
        style: { zIndex: newZ }
      });
      
      // Also directly manipulate DOM for immediate feedback
      nextTick(() => {
        const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
        if (nodeElement) {
          nodeElement.style.zIndex = newZ;
          
          // Also update custom-node if it exists
          const customNode = nodeElement.querySelector('.custom-node');
          if (customNode) {
            customNode.style.zIndex = newZ;
          }
        }
      });
    }
  }
};

const sendToBack = () => {
  if (selectedNodeData.value && selectedNodeData.value.data?.isShape) {
    // Find the lowest z-index in the current shapes
    let lowestZ = Number.MAX_SAFE_INTEGER;
    if (processStore.currentProcess && processStore.currentProcess.nodes) {
      processStore.currentProcess.nodes.forEach(node => {
        if (node.data?.isShape && node.id !== selectedNodeData.value.id) {
          const nodeZ = parseInt(node.data.zIndex || 0, 10);
          lowestZ = Math.min(lowestZ, nodeZ);
        }
      });
    }
    
    // If no other shapes were found, set to 0
    if (lowestZ === Number.MAX_SAFE_INTEGER) {
      lowestZ = 0;
    }
    
    // Set to lower than the lowest found (subtract 10 to ensure it's clearly below)
    const newZ = Math.max(0, lowestZ - 10);
    selectedNodeData.value.data.zIndex = newZ;
    
    // Update in store
    updateNodeInStore();
    
    // Force update the node style in the canvas
    if (processFlowCanvas.value && processFlowCanvas.value.updateNode) {
      processFlowCanvas.value.updateNode(selectedNodeData.value.id, {
        style: { zIndex: newZ }
      });
      
      // Also directly manipulate DOM for immediate feedback
      nextTick(() => {
        const nodeElement = document.querySelector(`[data-id="${selectedNodeData.value.id}"]`);
        if (nodeElement) {
          nodeElement.style.zIndex = newZ;
          
          // Also update custom-node if it exists
          const customNode = nodeElement.querySelector('.custom-node');
          if (customNode) {
            customNode.style.zIndex = newZ;
          }
        }
      });
    }
  }
};
</script>

<template>
<div>
  <client-only>
    <div class="process-builder flex flex-col h-screen bg-white">
    <!-- Header Bar -->
    <header
      class="bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between shadow-sm"
    >
      <!-- Left section - Logo and navigation -->
      <div class="flex items-center gap-4">
        <Icon
          @click="confirmNavigation('/process-builder/manage')"
          name="ph:arrow-circle-left-duotone"
          class="cursor-pointer w-6 h-6 hover:text-gray-600 text-gray-500"
        />
        <div class="flex items-center gap-3">
          <img
            src="@/assets/img/logo/logo-word-black.svg"
            alt="Corrad Logo"
            class="h-8"
          />
          <div class="border-l border-gray-300 pl-3">
            <h1 class="text-xl font-semibold text-gray-900">Process Builder</h1>
            <p class="text-sm text-gray-500">Create business processes with drag and drop</p>
          </div>
        </div>
      </div>

      <!-- Middle section - Process name and Panel Controls -->
      <div class="flex-1 flex justify-center items-center mx-2 md:mx-4 gap-4">
        <!-- Panel toggle controls - Always visible when process is loaded -->
        <div v-if="hasCurrentProcess" class="flex items-center gap-1">
          <RsButton 
            @click="toggleLeftPanel" 
            variant="tertiary" 
            size="sm"
            :class="{ 
              'bg-blue-100 text-blue-600 border-blue-200': showLeftPanel, 
              'bg-gray-100 text-gray-600 border-gray-200': !showLeftPanel 
            }"
            class="p-2 border transition-all duration-200 hover:scale-105 relative"
            title="Toggle Components Panel (Ctrl+1)"
          >
            <Icon name="material-symbols:widgets" class="w-4 h-4" />
            <span v-if="!showLeftPanel" class="absolute -top-1 -right-1 w-2 h-2 bg-orange-400 rounded-full"></span>
          </RsButton>
          <RsButton 
            @click="toggleRightPanel" 
            variant="tertiary" 
            size="sm"
            :class="{ 
              'bg-blue-100 text-blue-600 border-blue-200': showRightPanel, 
              'bg-gray-100 text-gray-600 border-gray-200': !showRightPanel 
            }"
            class="p-2 border transition-all duration-200 hover:scale-105 relative"
            title="Toggle Properties Panel (Ctrl+2)"
          >
            <Icon name="material-symbols:tune" class="w-4 h-4" />
            <span v-if="!showRightPanel" class="absolute -top-1 -right-1 w-2 h-2 bg-orange-400 rounded-full"></span>
          </RsButton>
          <RsButton 
            @click="toggleBothPanels" 
            variant="tertiary" 
            size="sm"
            :class="{ 
              'bg-blue-100 text-blue-600 border-blue-200': showLeftPanel && showRightPanel, 
              'bg-gray-100 text-gray-600 border-gray-200': !(showLeftPanel && showRightPanel) 
            }"
            class="p-2 hidden md:block border transition-all duration-200 hover:scale-105 relative"
            title="Toggle Both Panels (Ctrl+3)"
          >
            <Icon name="material-symbols:view-sidebar" class="w-4 h-4" />
            <span v-if="!showLeftPanel || !showRightPanel" class="absolute -top-1 -right-1 w-2 h-2 bg-orange-400 rounded-full"></span>
          </RsButton>
        </div>

        <!-- Process name input -->
        <FormKit
          v-if="hasCurrentProcess"
          v-model="processStore.currentProcess.name"
          type="text"
          placeholder="Process Name"
          validation="required"
          validation-visibility="live"
          :validation-messages="{ required: 'Please enter a process name' }"
          class="process-name-input max-w-xs md:max-w-md"
          :classes="{
            outer: 'mb-0 w-full',
          }"
        />
        <div v-else class="text-sm md:text-lg font-medium text-gray-400 hidden sm:block">No Process Selected</div>
      </div>

      <!-- Right section - Actions -->
      <div class="flex items-center">
        <!-- Primary actions -->
        <div class="flex items-center mr-1 md:mr-2 border-r border-gray-200 pr-1 md:pr-2">
          <RsButton @click="saveProcess" variant="primary" size="sm" class="mr-1 md:mr-2" :disabled="!hasCurrentProcess || isSaving">
            <Icon v-if="isSaving" name="material-symbols:progress-activity" class="mr-0 md:mr-1 animate-spin" />
            <Icon v-else name="material-symbols:save" class="mr-0 md:mr-1" />
            <span class="hidden md:inline">{{ isSaving ? 'Saving...' : 'Save' }}</span>
          </RsButton>
        </div>
        
        <!-- Copy/Paste actions -->
        <div class="flex items-center mr-1 md:mr-2 border-r border-gray-200 pr-1 md:pr-2">
          <RsButton 
            @click="copySelectedElements" 
            variant="secondary" 
            size="sm" 
            class="mr-1" 
            :disabled="!canCopy"
            :title="`Copy selected elements (Ctrl+C)${currentSelectionInfo ? ' - ' + currentSelectionInfo : clipboardInfo ? ' - Current: ' + clipboardInfo : ''}`"
          >
            <Icon name="material-symbols:content-copy" class="mr-0 md:mr-1" />
            <span class="hidden md:inline">Copy</span>
          </RsButton>
          <RsButton 
            @click="pasteElements" 
            variant="secondary" 
            size="sm" 
            :disabled="!canPaste"
            :title="`Paste elements (Ctrl+V)${clipboardInfo ? ' - ' + clipboardInfo : ''}`"
          >
            <Icon name="material-symbols:content-paste" class="mr-0 md:mr-1" />
            <span class="hidden md:inline">Paste</span>
          </RsButton>
          
          <!-- Selection indicator -->
          <div v-if="currentSelectionInfo && !clipboardInfo" class="ml-2 px-2 py-1 bg-green-100 text-green-700 text-xs rounded-md border border-green-200 hidden sm:block" :title="`Selected: ${currentSelectionInfo}. Press Ctrl+C to copy.`">
            <Icon name="material-symbols:select-all" class="w-3 h-3 mr-1" />
            {{ currentSelectionInfo }}
          </div>
          
          <!-- Clipboard indicator -->
          <div v-if="clipboardInfo" class="ml-2 px-2 py-1 bg-blue-100 text-blue-700 text-xs rounded-md border border-blue-200 hidden sm:block" :title="`Clipboard contains: ${clipboardInfo}. You can paste this in any process tab.`">
            <Icon name="material-symbols:content-paste" class="w-3 h-3 mr-1" />
            {{ clipboardInfo }}
          </div>
        </div>
        

        
        <!-- Secondary actions -->
        <div class="flex items-center">
          <div class="dropdown relative">
            <RsButton @click="showDropdown = !showDropdown" variant="tertiary" size="sm" class="flex items-center">
              <Icon name="material-symbols:more-vert" class="w-4 h-4 md:w-5 md:h-5" />
            </RsButton>
            
            <div v-if="showDropdown" class="dropdown-menu absolute right-0 mt-2 bg-white rounded shadow-lg py-1 z-10 w-48 text-gray-800">
              <!-- Process Actions -->
              <div class="px-3 py-1 text-xs font-medium text-gray-500 uppercase tracking-wide">
                Process Actions
              </div>
              <button @click="showTemplatesModal = true; showDropdown = false" :disabled="!hasCurrentProcess" class="w-full text-left px-4 py-2 hover:bg-gray-100 flex items-center disabled:opacity-50">
                <Icon name="material-symbols:description-outline" class="mr-2 w-4 h-4" />
                <span>Templates</span>
              </button>
              <button v-if="processStore.currentProcess && processStore.currentProcess.id" @click="showProcessHistoryModal = true; showDropdown = false" class="w-full text-left px-4 py-2 hover:bg-gray-100 flex items-center">
                <Icon name="material-symbols:history" class="mr-2 w-4 h-4" />
                <span>History</span>
              </button>
              <button @click="showExportModal = true; showDropdown = false" :disabled="!hasCurrentProcess" class="w-full text-left px-4 py-2 hover:bg-gray-100 flex items-center disabled:opacity-50">
                <Icon name="material-symbols:download" class="mr-2 w-4 h-4" />
                <span>Export</span>
              </button>
              
              <!-- Clipboard Actions -->
              <div class="px-3 py-1 text-xs font-medium text-gray-500 uppercase tracking-wide mt-2">
                Clipboard
              </div>
              <div v-if="clipboardInfo" class="px-4 py-2 text-xs text-gray-600 bg-gray-50 border-l-2 border-blue-400">
                <div class="flex items-center">
                  <Icon name="material-symbols:content-paste" class="w-3 h-3 mr-1" />
                  <span>{{ clipboardInfo }} ready to paste</span>
                </div>
              </div>
              <button @click="clearClipboard(); showDropdown = false" :disabled="!clipboardInfo" class="w-full text-left px-4 py-2 hover:bg-gray-100 flex items-center disabled:opacity-50">
                <Icon name="mdi:clipboard-remove-outline" class="mr-2 w-4 h-4" />
                <span>Clear Clipboard</span>
              </button>
              
              <!-- Settings -->
              <div class="px-3 py-1 text-xs font-medium text-gray-500 uppercase tracking-wide mt-2">
                Settings
              </div>
              <button @click="showProcessSettings = true; showDropdown = false" class="w-full text-left px-4 py-2 hover:bg-gray-100 flex items-center">
                <Icon name="material-symbols:tune" class="mr-2 w-4 h-4" />
                <span>Process Settings</span>
              </button>
            </div>
          </div>
        </div>
      </div>
    </header>

    <!-- Main Content Area -->
    <div class="flex-1 flex overflow-hidden relative h-full" v-if="hasCurrentProcess">
      <!-- Left Panel - Components -->
      <div 
        v-show="showLeftPanel"
        :class="{
          'absolute inset-y-0 left-0 z-20 bg-white shadow-lg': isMobile,
          'absolute inset-y-0 left-0 z-10 bg-white shadow-md': isTablet,
          'relative w-60': !isMobile && !isTablet,
          'w-72': isMobile,
          'w-80': isTablet
        }"
        class="border-r border-gray-200 flex flex-col overflow-hidden transition-transform duration-300 ease-in-out"
      >
        <div class="bg-gray-100 p-3 flex items-center justify-between border-b border-gray-200">
          <h2 class="text-sm font-medium text-gray-700">Process Components</h2>
          <!-- Close button for all devices -->
          <button 
            @click="showLeftPanel = false"
            class="p-1 hover:bg-gray-200 rounded transition-colors"
            title="Close Panel (Ctrl+1)"
          >
            <Icon name="material-symbols:close" class="w-4 h-4 text-gray-500" />
          </button>
        </div>
        <div class="flex-1 overflow-y-auto">
          <ProcessBuilderComponents @add-component="onAddComponent" />
        </div>
      </div>

      <!-- Center Panel - Process Canvas -->
      <div class="flex-1 relative h-full" :class="{ 'bg-gray-50': !showLeftPanel && !showRightPanel }">
        <!-- Canvas State Indicator -->
        <div v-if="!showLeftPanel && !showRightPanel" class="absolute top-4 left-1/2 transform -translate-x-1/2 z-10 bg-white px-4 py-2 rounded-lg shadow-md border border-gray-200">
          <div class="flex items-center gap-2 text-sm text-gray-600">
            <Icon name="material-symbols:fullscreen" class="w-4 h-4 text-green-600" />
            <span>Full Canvas Mode</span>
            <span class="text-xs text-gray-400">Press Ctrl+3 to restore panels</span>
          </div>
        </div>
        
        <ProcessFlowCanvas 
          ref="processFlowCanvas"
          :initial-nodes="canvasNodes"
          :initial-edges="canvasEdges"
          :highlighted-node-id="highlightedNodeId"
          @node-selected="onNodeSelected"
          @edge-selected="onEdgeSelected"
          @pane-click="onPaneClick" 
          @nodes-change="onNodesChange"
          @edges-change="onEdgesChange"
          class="w-full h-full"
        />
        
        <!-- Mobile floating action buttons -->
        <div v-if="isMobile" class="absolute bottom-4 right-4 flex flex-col gap-2">
          <RsButton 
            @click="toggleLeftPanel"
            variant="primary"
            class="rounded-full w-12 h-12 p-0 shadow-lg"
            :class="{ 'bg-blue-600': showLeftPanel }"
          >
            <Icon name="material-symbols:widgets" class="w-6 h-6" />
          </RsButton>
          <RsButton 
            @click="toggleRightPanel"
            variant="primary"
            class="rounded-full w-12 h-12 p-0 shadow-lg"
            :class="{ 'bg-blue-600': showRightPanel }"
          >
            <Icon name="material-symbols:tune" class="w-6 h-6" />
          </RsButton>
        </div>
      </div>

      <!-- Right Panel - Properties -->
      <div 
        v-show="showRightPanel"
        :class="{
          'absolute inset-y-0 right-0 z-20 bg-white shadow-lg': isMobile,
          'absolute inset-y-0 right-0 z-10 bg-white shadow-md': isTablet,
          'relative w-64': !isMobile && !isTablet,
          'w-72': isMobile,
          'w-80': isTablet
        }"
        class="border-l border-gray-200 flex flex-col overflow-hidden transition-transform duration-300 ease-in-out"
      >
        <div class="bg-gray-100 p-3 flex items-center justify-between border-b border-gray-200">
          <h2 class="text-sm font-medium text-gray-700">Properties</h2>
          <!-- Close button for all devices -->
          <button 
            @click="showRightPanel = false"
            class="p-1 hover:bg-gray-200 rounded transition-colors"
            title="Close Panel (Ctrl+2)"
          >
            <Icon name="material-symbols:close" class="w-4 h-4 text-gray-500" />
          </button>
        </div>
        <div class="flex-1 overflow-y-auto overflow-x-hidden">
          <!-- Show variable manager when no node is selected -->
          <VariableManager v-if="!selectedNodeData && !selectedEdgeData" :key="`variables-${variablesUpdateKey}`" />
          
          <!-- Show edge properties when an edge is selected -->
          <div v-else-if="selectedEdgeData" class="flex flex-col h-full">
            <!-- Edge Header -->
            <div class="p-4 border-b border-gray-200 bg-gray-50">
              <div class="space-y-3">
                <!-- Row 1: Title with Icon -->
                <div class="flex items-center space-x-2">
                  <div class="w-8 h-8 rounded-lg flex items-center justify-center text-white text-sm font-medium bg-blue-500 flex-shrink-0">
                    <Icon name="material-symbols:timeline" class="w-4 h-4" />
                  </div>
                  <div class="min-w-0 flex-1">
                    <h3 class="text-sm font-semibold text-gray-900 break-words">Connection</h3>
                  </div>
                </div>
                
                <!-- Row 2: Edge ID -->
                <div class="flex items-center space-y-0">
                  <p class="text-xs text-gray-500 break-all">{{ selectedEdgeData.id }}</p>
                </div>
                
                <!-- Row 3: Action Buttons -->
                <div class="flex items-center">
                  <RsButton
                    @click="copySelectedElements"
                    variant="secondary-text"
                    size="sm"
                    icon
                    :title="`Copy Edge (Ctrl+C)${currentSelectionInfo ? ' - ' + currentSelectionInfo : clipboardInfo ? ' - Current: ' + clipboardInfo : ''}`"
                    class="modern-icon-btn"
                  >
                    <Icon name="material-symbols:content-copy" class="w-4 h-4" />
                  </RsButton>
                  <RsButton
                    @click="deleteEdge"
                    variant="danger-text"
                    size="sm"
                    icon
                    :title="'Delete Edge'"
                    class="modern-icon-btn"
                  >
                    <Icon name="material-symbols:delete" class="w-4 h-4" />
                  </RsButton>
                </div>
              </div>
            </div>

            <!-- Edge Properties -->
            <div class="flex-1 overflow-y-auto overflow-x-hidden">
              <div class="p-4 space-y-4">
                <div>
                  <h4 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                    <Icon name="material-symbols:edit" class="w-4 h-4 mr-2" />
                    Edge Properties
                  </h4>
                  
                  <!-- Edge Label -->
                  <div class="mb-3">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Label</label>
                    <input
                      v-model="selectedEdgeData.label"
                      type="text"
                      class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                      placeholder="Enter edge label"
                      @input="updateEdgeLabel(selectedEdgeData.label)"
                    />
                  </div>

                  <!-- Source Node -->
                  <div class="mb-3">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Source Node</label>
                    <div class="px-3 py-2 text-sm bg-gray-100 border border-gray-300 rounded-md">
                      {{ selectedEdgeData.sourceNode?.label || selectedEdgeData.source }}
                    </div>
                  </div>

                  <!-- Target Node -->
                  <div class="mb-3">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Target Node</label>
                    <div class="px-3 py-2 text-sm bg-gray-100 border border-gray-300 rounded-md">
                      {{ selectedEdgeData.targetNode?.label || selectedEdgeData.target }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          
          <!-- Show node properties when a node is selected -->
          <div v-else class="flex flex-col h-full">
            <!-- Node/Shape Header -->
            <div class="p-4 border-b border-gray-200 bg-gray-50">
              <div class="space-y-1">
                <!-- Row 1: Title with Icon -->
                <div class="flex items-center space-x-2">
                  <div class="w-8 h-8 rounded-lg flex items-center justify-center text-white text-sm font-medium flex-shrink-0"
                       :style="{ backgroundColor: nodeBorderColor }">
                    <Icon :name="`material-symbols:${getNodeIcon(selectedNodeData.type)}`" 
                          class="w-4 h-4" />
                  </div>
                  <div class="min-w-0 flex-1">
                    <h3 class="text-sm font-semibold text-gray-900 capitalize break-words">
                      {{ selectedNodeData.data?.isShape ? 'Shape' : 'Node' }}: {{ selectedNodeData.type.replace('-', ' ') }}
                    </h3>
                  </div>
                </div>
                
                <!-- Row 2: Node ID -->
                <div class="flex items-center">
                  <p class="text-xs text-gray-500 break-all">{{ selectedNodeData.id }}</p>
                </div>
                
                <!-- Row 3: Action Buttons -->
                <div v-if="canShowNodeActions" class="flex items-center gap-2">
                  <RsButton
                    @click="duplicateNode"
                    variant="secondary-text"
                    size="sm"
                    icon
                    :title="'Duplicate Node'"
                    class="modern-icon-btn"
                  >
                    <Icon name="material-symbols:content-copy-outline" class="w-5 h-5" />
                  </RsButton>
                  <RsButton
                    @click="deleteNode"
                    variant="danger-text"
                    size="sm"
                    icon
                    :title="'Delete Node'"
                    class="modern-icon-btn"
                  >
                    <Icon name="material-symbols:delete" class="w-5 h-5" />
                  </RsButton>
                </div>
              </div>
            </div>

            <!-- Scrollable Content -->
            <div class="flex-1 overflow-y-auto overflow-x-hidden">
              <!-- Basic Properties Section -->
              <div class="p-4 space-y-4">
                <div>
                  <h4 v-if="!selectedNodeData.data?.isShape || selectedNodeData.type === 'text-annotation'" class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                    <Icon name="material-symbols:edit" class="w-4 h-4 mr-2" />
                    Basic Properties
                  </h4>
                  
                  <!-- Node Label (only for process nodes and text annotations, not other shapes) -->
                  <div v-if="!selectedNodeData.data?.isShape || selectedNodeData.type === 'text-annotation'" class="mb-3">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Label</label>
                    <input
                      v-model="nodeLabel"
                      type="text"
                      class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                      placeholder="Enter node label"
                    />
                  </div>

                  <!-- Node Description (only for process nodes and text annotations, not other shapes) -->
                  <div v-if="!selectedNodeData.data?.isShape || selectedNodeData.type === 'text-annotation'" class="mb-3">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Description</label>
                    <textarea
                      v-model="nodeDescription"
                      rows="2"
                      class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                      placeholder="Enter node description"
                    />
                  </div>

                  <!-- Node Shape Selector (only for non-start/end nodes and non-shapes) -->
                  <div v-if="selectedNodeData.type !== 'start' && selectedNodeData.type !== 'end' && !selectedNodeData.data?.isShape">
                    <label class="block text-xs font-medium text-gray-600 mb-1">Shape</label>
                    <select
                      v-model="nodeShape"
                      class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                    >
                      <option v-for="shape in shapeOptions" :key="shape.value" :value="shape.value">
                        {{ shape.label }}
                      </option>
                    </select>
                    <div class="mt-1 text-xs text-gray-500 flex items-center">
                      <Icon :name="`material-symbols:${shapeOptions.find(s => s.value === nodeShape)?.icon || 'crop_din'}`" class="w-3 h-3 mr-1" />
                      {{ shapeOptions.find(s => s.value === nodeShape)?.label || 'Rectangle' }}
                    </div>
                  </div>

                                      <!-- Size Controls for Shapes -->
                    <div v-if="selectedNodeData.data?.isShape" class="space-y-4">
                      <h4 class="text-sm font-medium text-gray-700 mb-2 flex items-center">
                        <Icon name="material-symbols:straighten" class="w-4 h-4 mr-2" />
                        Size
                      </h4>
                      
                      <div class="grid grid-cols-2 gap-3">
                        <div>
                          <label class="block text-xs font-medium text-gray-600 mb-1">Width</label>
                          <input
                            v-model.number="selectedNodeData.data.width"
                            type="number"
                            min="50"
                            max="2000"
                            class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            @input="updateShapeSize"
                          />
                        </div>
                        <div>
                          <label class="block text-xs font-medium text-gray-600 mb-1">Height</label>
                          <input
                            v-model.number="selectedNodeData.data.height"
                            type="number"
                            min="50"
                            max="2000"
                            class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            @input="updateShapeSize"
                          />
                        </div>
                      </div>
                      
                      <!-- Z-Index control with heading -->
                      <div class="mt-6 pt-4 border-t border-gray-100">
                        <h4 class="text-sm font-medium text-gray-700 mb-2 flex items-center">
                          <Icon name="material-symbols:layers" class="w-4 h-4 mr-2" />
                          Layer Position
                        </h4>
                        
                        <div class="mb-3">
                          <label class="block text-xs font-medium text-gray-600 mb-1">Stack Order (Z-Index)</label>
                          <input
                            v-model.number="nodeZIndex"
                            type="number"
                            class="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            placeholder="0"
                          />
                          <div class="flex justify-center space-x-2 mt-2">
                            <button 
                              @click="sendToBack" 
                              title="Send to Back" 
                              class="p-2 bg-gray-100 hover:bg-gray-200 rounded border border-gray-300"
                            >
                              <Icon name="material-symbols:vertical-align-bottom" class="w-4 h-4 text-gray-600" />
                            </button>
                            <button 
                              @click="sendBackward" 
                              title="Send Backward" 
                              class="p-2 bg-gray-100 hover:bg-gray-200 rounded border border-gray-300"
                            >
                              <Icon name="material-symbols:arrow-downward" class="w-4 h-4 text-gray-600" />
                            </button>
                            <button 
                              @click="bringForward" 
                              title="Bring Forward" 
                              class="p-2 bg-gray-100 hover:bg-gray-200 rounded border border-gray-300"
                            >
                              <Icon name="material-symbols:arrow-upward" class="w-4 h-4 text-gray-600" />
                            </button>
                            <button 
                              @click="bringToFront" 
                              title="Bring to Front" 
                              class="p-2 bg-gray-100 hover:bg-gray-200 rounded border border-gray-300"
                            >
                              <Icon name="material-symbols:vertical-align-top" class="w-4 h-4 text-gray-600" />
                            </button>
                          </div>
                        </div>
                        
                        <div class="bg-blue-50 p-2 rounded-md">
                          <p class="text-xs text-blue-700">
                            <strong>Tip:</strong> Use these controls to arrange the stacking order of shapes. Higher values appear on top of other shapes.
                          </p>
                        </div>
                      </div>
                    </div>
                </div>
              </div>

              <!-- Appearance Section -->
              <div class="p-4 border-t border-gray-200">
                <h4 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                  <Icon name="material-symbols:palette" class="w-4 h-4 mr-2" />
                  Appearance
                </h4>
                
                <div class="space-y-3">
                  <!-- Background Color -->
                  <div>
                    <label class="block text-xs font-medium text-gray-600 mb-2">Background</label>
                    <div class="flex items-center space-x-2">
                      <input
                        v-model="nodeBackgroundColor"
                        type="color"
                        class="w-8 h-8 border border-gray-300 rounded cursor-pointer flex-shrink-0"
                      />
                      <input
                        v-model="nodeBackgroundColor"
                        type="text"
                        pattern="^#[0-9a-fA-F]{6}$"
                        title="Enter a valid hex color (e.g., #ffffff)"
                        maxlength="7"
                        @input="validateColorInput"
                        class="flex-1 px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
                        placeholder="#ffffff"
                      />
                    </div>
                  </div>
                  
                  <!-- Border Color -->
                  <div>
                    <label class="block text-xs font-medium text-gray-600 mb-2">Border</label>
                    <div class="flex items-center space-x-2">
                      <input
                        v-model="nodeBorderColor"
                        type="color"
                        class="w-8 h-8 border border-gray-300 rounded cursor-pointer flex-shrink-0"
                      />
                      <input
                        v-model="nodeBorderColor"
                        type="text"
                        pattern="^#[0-9a-fA-F]{6}$"
                        title="Enter a valid hex color (e.g., #dddddd)"
                        maxlength="7"
                        @input="validateColorInput"
                        class="flex-1 px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
                        placeholder="#dddddd"
                      />
                    </div>
                  </div>
                  
                  <!-- Text Color -->
                  <div>
                    <label class="block text-xs font-medium text-gray-600 mb-2">Text</label>
                    <div class="flex items-center space-x-2">
                      <input
                        v-model="nodeTextColor"
                        type="color"
                        class="w-8 h-8 border border-gray-300 rounded cursor-pointer flex-shrink-0"
                      />
                      <input
                        v-model="nodeTextColor"
                        type="text"
                        pattern="^#[0-9a-fA-F]{6}$"
                        title="Enter a valid hex color (e.g., #333333)"
                        maxlength="7"
                        @input="validateColorInput"
                        class="flex-1 px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
                        placeholder="#333333"
                      />
                    </div>
                  </div>
                  
                  <!-- Reset Colors Button -->
                  <button
                    @click="resetNodeColors"
                    class="w-full mt-3 py-2 px-3 text-xs bg-gray-100 text-gray-700 border border-gray-300 rounded hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors"
                  >
                    <Icon name="material-symbols:refresh" class="w-3 h-3 mr-1" />
                    Reset to Default
                  </button>
                </div>
              </div>

              <!-- Configuration Section (only for process nodes, not shapes) -->
              <div v-if="selectedNodeData.type !== 'start' && selectedNodeData.type !== 'end' && !selectedNodeData.data?.isShape" class="p-4 border-t border-gray-200">
                <h4 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                  <Icon name="material-symbols:settings" class="w-4 h-4 mr-2" />
                  Configuration
                </h4>
                
                <!-- Form Selection for Form Nodes -->
                <div v-if="selectedNodeData.type === 'form'">
                  <p class="text-xs text-gray-600 mb-3">Configure form submission behavior and data mapping.</p>
                  <RsButton @click="showFormConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:description" class="w-4 h-4 mr-2" />
                    Configure Form Task
                  </RsButton>
                </div>

                <!-- API Configuration for API Nodes -->
                <div v-if="selectedNodeData.type === 'api'">
                  <p class="text-xs text-gray-600 mb-3">Set up API endpoint, request parameters, and response handling.</p>
                  <RsButton @click="showApiConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:api" class="w-4 h-4 mr-2" />
                    Configure API Call
                  </RsButton>
                </div>

                <!-- Gateway Conditions -->
                <div v-if="selectedNodeData.type === 'gateway'">
                  <p class="text-xs text-gray-600 mb-3">Define decision conditions and workflow paths.</p>
                  <RsButton @click="showGatewayConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:call-split" class="w-4 h-4 mr-2" />
                    Configure Decision Paths
                  </RsButton>
                </div>
                
                <!-- Business Rule Configuration -->
                <div v-if="selectedNodeData.type === 'business-rule'">
                  <p class="text-xs text-gray-600 mb-3">Set up business logic conditions and actions.</p>
                  <RsButton @click="showBusinessRuleConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:rule" class="w-4 h-4 mr-2" />
                    Configure Business Rule
                  </RsButton>
                </div>
                
                <!-- Notification Configuration -->
                <div v-if="selectedNodeData.type === 'notification'">
                  <p class="text-xs text-gray-600 mb-3">Configure notification recipients, content, and delivery method.</p>
                  <RsButton @click="showNotificationConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:notifications" class="w-4 h-4 mr-2" />
                    Configure Notification
                  </RsButton>
                </div>
                
                <!-- Script Configuration -->
                <div v-if="selectedNodeData.type === 'script'">
                  <p class="text-xs text-gray-600 mb-3">Write custom scripts and define execution parameters.</p>
                  <RsButton @click="showScriptConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:code" class="w-4 h-4 mr-2" />
                    Configure Script Task
                  </RsButton>
                </div>

                <!-- HTML Configuration -->
                <div v-if="selectedNodeData.type === 'html'">
                  <p class="text-xs text-gray-600 mb-3">Configure HTML content and output variables.</p>
                  <RsButton @click="showHtmlConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:html" class="w-4 h-4 mr-2" />
                    Configure HTML Node
                  </RsButton>
                </div>

                <!-- Sub-process Configuration -->
                <div v-if="selectedNodeData.type === 'subprocess'">
                  <p class="text-xs text-gray-600 mb-3">Select a process to execute as a sub-process.</p>
                  <RsButton @click="showSubprocessConfigModal = true" variant="primary" class="w-full">
                    <Icon name="material-symbols:hub" class="w-4 h-4 mr-2" />
                    Configure Sub-process
                  </RsButton>
                </div>
              </div>

              <!-- Shape Information -->
              <div v-if="selectedNodeData.data?.isShape" class="p-4 border-t border-gray-200">
                <h4 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
                  <Icon name="material-symbols:info" class="w-4 h-4 mr-2" />
                  Shape Information
                </h4>
                <div class="bg-blue-50 border border-blue-200 rounded-lg p-3">
                  <p class="text-sm text-blue-700">
                    <strong>Design Element:</strong> This is a decorative shape used for visual organization and layout. 
                    It doesn't participate in the process flow and cannot be connected to other nodes.
                  </p>
                  <div class="mt-2 text-xs text-blue-600">
                    <div class="flex items-center">
                      <Icon name="material-symbols:palette" class="w-3 h-3 mr-1" />
                      Use the appearance section above to customize colors and styling
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Backdrop for mobile panels -->
      <div 
        v-if="(isMobile || isTablet) && (showLeftPanel || showRightPanel)"
        @click="showLeftPanel = false; showRightPanel = false"
        class="absolute inset-0 bg-black bg-opacity-50 z-5"
      ></div>
    </div>

    <!-- Empty state - No process selected -->
    <div v-else class="flex-1 flex items-center justify-center bg-gray-50">
      <div class="text-center p-8 max-w-md">
        <Icon name="material-symbols:flowchart" class="w-16 h-16 mx-auto mb-4 text-gray-400" />
        <h2 class="text-xl font-semibold text-gray-800 mb-2">Create a New Process</h2>
        <p class="text-gray-600 mb-6">Get started by creating a new process or navigate back to manage your existing processes.</p>
        
        <div class="space-y-3">
          <div class="mb-4">
            <FormKit
              v-model="newProcessName"
              type="text"
              label="Process Name"
              placeholder="Enter a name for your new process"
              validation="required"
            />
            
            <FormKit
              v-model="newProcessDescription"
              type="textarea"
              label="Description (Optional)"
              placeholder="Enter a description"
              :rows="3"
            />
          </div>
          
          <div class="flex justify-center gap-4">
            <RsButton @click="createNewProcess" variant="primary" :disabled="!newProcessName.trim()">
              <Icon name="material-symbols:add" class="mr-1" />
              Create Process
            </RsButton>
            
            <RsButton @click="confirmNavigation('/process-builder/manage')" variant="tertiary">
              <Icon name="material-symbols:arrow-back" class="mr-1" />
              Back to Processes
            </RsButton>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Unsaved changes dialog -->
    <RsModal v-model="showUnsavedChangesModal" title="Unsaved Changes" size="md" position="center">
      <div class="p-4">
        <div class="flex items-center mb-4">
          <Icon name="material-symbols:warning-outline" class="text-yellow-500 w-8 h-8 mr-3" />
          <div>
            <p class="text-gray-600">You have unsaved changes that will be lost if you leave the page.</p>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="flex justify-end gap-2">
          <RsButton @click="cancelNavigation" variant="tertiary">
            Stay on this Page
          </RsButton>
          <RsButton @click="proceedWithNavigation" variant="danger">
            Discard Changes
          </RsButton>
        </div>
      </template>
    </RsModal>
    
    <!-- Form Task Configuration Modal -->
    <FormNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'form'"
      v-model="showFormConfigModal"
      :key="`form-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleFormNodeUpdate"
    />
    
    <!-- API Call Configuration Modal -->
    <ApiNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'api'"
      v-model="showApiConfigModal"
      :key="`api-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleApiNodeUpdate"
    />
    
    <!-- Gateway/Decision Point Configuration Modal -->
    <GatewayConditionManagerModal
      v-if="selectedNodeData && selectedNodeData.type === 'gateway'"
      v-model="showGatewayConfigModal"
      :key="`gateway-${selectedNodeData.id}-${variablesUpdateKey}`"
      :conditions="selectedNodeData.data.conditions || []"
      :availableVariables="gatewayAvailableVariables"
      :defaultPath="selectedNodeData.data.defaultPath || 'Default'"
      @update:conditions="handleConditionUpdate"
      @update:defaultPath="handleDefaultPathUpdate"
    />
    
    <!-- Business Rule Configuration Modal -->
    <BusinessRuleNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'business-rule'"
      v-model="showBusinessRuleConfigModal"
      :key="`business-rule-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeId="selectedNodeData.id"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleBusinessRuleUpdate"
    />
    
    <!-- Notification Configuration Modal -->
    <NotificationNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'notification'"
      v-model="showNotificationConfigModal"
      :key="`notification-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleNotificationNodeUpdate"
    />
    
    <!-- Script Configuration Modal -->
    <ScriptNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'script'"
      v-model="showScriptConfigModal"
      :key="`script-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleScriptNodeUpdate"
    />

    <!-- HTML Configuration Modal -->
    <HtmlNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'html'"
      v-model="showHtmlConfigModal"
      :key="`html-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      :availableVariables="gatewayAvailableVariables"
      @update="handleHtmlNodeUpdate"
    />
    
    <!-- Sub-process Configuration Modal -->
    <SubprocessNodeConfigurationModal
      v-if="selectedNodeData && selectedNodeData.type === 'subprocess'"
      v-model="showSubprocessConfigModal"
      :key="`subprocess-${selectedNodeData.id}-${variablesUpdateKey}`"
      :nodeData="selectedNodeData.data"
      @update="handleSubprocessNodeUpdate"
    />
    
    <!-- Process Templates Modal -->
    <ProcessTemplatesModal
      v-model="showTemplatesModal"
      @select-template="applyProcessTemplate"
    />
    
    <!-- Process Settings Modal -->
    <ProcessSettingsModal
      v-model="showProcessSettings"
    />

    <!-- Process History Modal -->
    <ProcessHistoryModal
      :is-open="showProcessHistoryModal"
      :process-id="processStore.currentProcess?.id || ''"
      @close="showProcessHistoryModal = false"
      @restored="handleProcessRestored"
    />

    <!-- Export Canvas Modal -->
    <ExportCanvasModal
      :show="showExportModal"
      :process-name="processStore.currentProcess?.name || 'process'"
      @close="showExportModal = false"
      @export="handleExportCanvas"
    />
    </div>
  </client-only>
</div>
</template>

<style scoped>
.process-builder {
  --flow-node-selected-color: theme('colors.blue.500');
  --flow-background-color: theme('colors.gray.100');
  --flow-connection-path-color: theme('colors.gray.400');
  --flow-connection-path-hover-color: theme('colors.blue.400');
}

:deep(.custom-node) {
  border-radius: 4px;
  padding: 10px;
}

/* Shape classes for flowchart nodes */
:deep(.custom-node.shape-rectangle) {
  border-radius: 4px;
}

:deep(.custom-node.shape-rounded-rectangle) {
  border-radius: 12px;
}

:deep(.custom-node.shape-circle) {
  border-radius: 50%;
  min-width: 120px;
  min-height: 120px;
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

:deep(.custom-node.shape-circle .custom-node-content) {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:deep(.custom-node.shape-diamond) {
  transform: rotate(45deg);
  border-radius: 8px;
  min-width: 120px;
  min-height: 120px;
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

:deep(.custom-node.shape-diamond .custom-node-content) {
  transform: rotate(-45deg);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:deep(.custom-node.shape-hexagon) {
  position: relative;
  border-radius: 0;
  background: none;
  border: none;
  min-width: 140px;
  min-height: 80px;
}

:deep(.custom-node.shape-hexagon::before) {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  z-index: 0;
}

/* Special backgrounds for business-rule, notification, and api hexagon shapes */
:deep(.node-business-rule.shape-hexagon::before) {
  border-left: 4px solid var(--node-border-color, #9333ea);
}

:deep(.node-notification.shape-hexagon::before) {
  border-left: 4px solid var(--node-border-color, #3b82f6);
}

:deep(.node-api.shape-hexagon::before) {
  border-left: 4px solid var(--node-border-color, #10b981);
}

:deep(.node-gateway.shape-hexagon::before) {
  border: 2px solid var(--node-border-color, #FF9800);
}

:deep(.custom-node.shape-hexagon .custom-node-content) {
  position: relative;
  z-index: 1;
}

:deep(.custom-node.shape-parallelogram) {
  transform: skew(-20deg);
  border-radius: 4px;
  min-width: 140px;
}

:deep(.custom-node.shape-parallelogram .custom-node-content) {
  transform: skew(20deg);
}

:deep(.custom-node.shape-trapezoid) {
  position: relative;
  border-radius: 0;
  background: none;
  border: none;
  min-width: 140px;
  min-height: 80px;
}

:deep(.custom-node.shape-trapezoid::before) {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  clip-path: polygon(30% 0%, 70% 0%, 100% 100%, 0% 100%);
  z-index: 0;
}

/* Special backgrounds for business-rule, notification, and api trapezoid shapes */
:deep(.node-business-rule.shape-trapezoid::before) {
  border-left: 4px solid var(--node-border-color, #9333ea);
}

:deep(.node-notification.shape-trapezoid::before) {
  border-left: 4px solid var(--node-border-color, #3b82f6);
}

:deep(.node-api.shape-trapezoid::before) {
  border-left: 4px solid var(--node-border-color, #10b981);
}

:deep(.node-gateway.shape-trapezoid::before) {
  border: 2px solid var(--node-border-color, #FF9800);
}

:deep(.custom-node.shape-trapezoid .custom-node-content) {
  position: relative;
  z-index: 1;
}

/* Handle positioning adjustments for different shapes */

/* Circle shape handles */
:deep(.custom-node.shape-circle .vue-flow__handle) {
  width: 10px;
  height: 10px;
}

:deep(.custom-node.shape-circle .handle-top) {
  top: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-circle .handle-bottom) {
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-circle .handle-left) {
  left: -5px;
  top: 50%;
  transform: translateY(-50%);
}

:deep(.custom-node.shape-circle .handle-right) {
  right: -5px;
  top: 50%;
  transform: translateY(-50%);
}

/* Text overflow and positioning for all shapes */

/* Base text styling for all nodes */
:deep(.custom-node .custom-node-content) {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  word-wrap: break-word;
  hyphens: auto;
  color: var(--node-text-color, #333333);
}

/* Ensure all text elements in nodes inherit the custom text color */
:deep(.custom-node *:not(.icon):not([class^="validation-"])) {
  color: inherit !important;
}

/* Override for icons to inherit text color but maintain visibility */
:deep(.custom-node .material-icons) {
  color: inherit;
  opacity: 0.9;
}

/* Ensure icons in start and end nodes maintain their original colors */
:deep(.node-start .material-icons) {
  color: #16a34a !important;
  opacity: 1;
}

:deep(.node-end .material-icons) {
  color: #dc2626 !important;
  opacity: 1;
}

/* Special handling for colored status indicators - make them more visible */
:deep(.custom-node .node-rule-detail-value) {
  color: inherit;
  font-weight: 600;
}

/* Make labels slightly dimmed for hierarchy */
:deep(.custom-node .node-rule-detail-label) {
  color: inherit;
  opacity: 0.7;
  font-weight: 500;
  white-space: nowrap;
}

:deep(.custom-node .custom-node-content .custom-node-label) {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
  max-width: 100%;
  font-size: 12px;
  font-weight: 500;
  padding: 2px 4px;
}

/* Rectangle and rounded rectangle - allow more text */
:deep(.custom-node.shape-rectangle .custom-node-content .custom-node-label),
:deep(.custom-node.shape-rounded-rectangle .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 4;
  font-size: 13px;
  max-width: calc(100% - 8px);
}

/* Circle - more constrained text */
:deep(.custom-node.shape-circle .custom-node-content) {
  padding: 15px 10px;
}

:deep(.custom-node.shape-circle .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 2;
  font-size: 11px;
  max-width: 80px;
  line-height: 1.1;
}

/* Diamond - very constrained text due to angled shape */
:deep(.custom-node.shape-diamond .custom-node-content) {
  padding: 20px 15px;
  /* DO NOT rotate the content - keep text readable */
}

:deep(.custom-node.shape-diamond .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 2;
  font-size: 10px;
  max-width: 70px;
  line-height: 1.1;
}

/* Hexagon - moderate text space */
:deep(.custom-node.shape-hexagon .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 3;
  font-size: 11px;
  max-width: calc(100% - 20px);
}

/* Parallelogram - slight skew consideration */
:deep(.custom-node.shape-parallelogram .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 3;
  font-size: 12px;
  max-width: calc(100% - 16px);
}

/* Trapezoid - consider the angled sides */
:deep(.custom-node.shape-trapezoid .custom-node-content .custom-node-label) {
  -webkit-line-clamp: 3;
  font-size: 11px;
  max-width: calc(100% - 20px);
}

/* Responsive text sizing for smaller nodes */
:deep(.custom-node) {
  min-width: 100px;
  min-height: 60px;
}

:deep(.custom-node.shape-circle) {
  min-width: 120px;
  min-height: 120px;
}

:deep(.custom-node.shape-diamond) {
  min-width: 120px;
  min-height: 120px;
}

/* Handle text overflow gracefully with tooltips */
:deep(.custom-node .custom-node-content .custom-node-label[title]) {
  cursor: help;
}

/* Improve readability on hover for overflowed text */
:deep(.custom-node:hover .custom-node-content .custom-node-label) {
  opacity: 0.8;
}

/* Additional text styling for node details */
:deep(.custom-node .node-description) {
  font-size: 10px;
  color: var(--node-text-color, #6b7280);
  text-align: center;
  line-height: 1.2;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin: 2px 0;
}

:deep(.custom-node .node-rule-detail) {
  font-size: 9px;
  margin: 1px 0;
}

:deep(.custom-node .node-rule-detail-value) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 60px;
}

/* Shape-specific adjustments for detailed content */
:deep(.custom-node.shape-circle .node-description),
:deep(.custom-node.shape-circle .node-rule-detail) {
  font-size: 8px;
}

:deep(.custom-node.shape-diamond .node-description),
:deep(.custom-node.shape-diamond .node-rule-detail) {
  font-size: 7px;
  /* Keep text readable - do not rotate */
}

:deep(.custom-node.shape-diamond .node-rule-detail-value) {
  max-width: 40px;
}

/* Better spacing for different node types */
:deep(.custom-node .gateway-details),
:deep(.custom-node .node-details) {
  width: 100%;
  padding: 2px 4px;
  overflow: hidden;
}

/* Responsive font sizing based on node size */
@media (max-width: 768px) {
  :deep(.custom-node .custom-node-label) {
    font-size: 10px;
  }
  
  :deep(.custom-node .node-description) {
    font-size: 8px;
  }
  
  :deep(.custom-node .node-rule-detail) {
    font-size: 7px;
  }
}

/* Diamond shape handles */
:deep(.custom-node.shape-diamond .vue-flow__handle) {
  width: 10px;
  height: 10px;
}

:deep(.custom-node.shape-diamond .handle-top) {
  top: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-diamond .handle-bottom) {
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-diamond .handle-left) {
  left: -5px;
  top: 50%;
  transform: translateY(-50%);
}

:deep(.custom-node.shape-diamond .handle-right) {
  right: -5px;
  top: 50%;
  transform: translateY(-50%);
}

/* Hexagon shape handles */
:deep(.custom-node.shape-hexagon .vue-flow__handle) {
  width: 10px;
  height: 10px;
}

:deep(.custom-node.shape-hexagon .handle-top) {
  top: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-hexagon .handle-bottom) {
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-hexagon .handle-left) {
  left: 5px;
  top: 50%;
  transform: translateY(-50%);
}

:deep(.custom-node.shape-hexagon .handle-right) {
  right: 5px;
  top: 50%;
  transform: translateY(-50%);
}

/* Parallelogram shape handles */
:deep(.custom-node.shape-parallelogram .vue-flow__handle) {
  width: 10px;
  height: 10px;
}

/* Trapezoid shape handles */
:deep(.custom-node.shape-trapezoid .vue-flow__handle) {
  width: 10px;
  height: 10px;
}

:deep(.custom-node.shape-trapezoid .handle-top) {
  top: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-trapezoid .handle-bottom) {
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
}

:deep(.custom-node.shape-trapezoid .handle-left) {
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
}

:deep(.custom-node.shape-trapezoid .handle-right) {
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
}

/* Ensure handles have higher z-index for all shapes */
:deep(.custom-node .vue-flow__handle) {
  z-index: 1001 !important;
  border: 2px solid white;
  background: #555;
  border-radius: 50%;
}

:deep(.custom-node .vue-flow__handle:hover) {
  background: #3b82f6;
  border-color: white;
  transform: scale(1.2);
}

:deep(.custom-node.selected) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

/* Selection highlighting for shaped nodes */
:deep(.custom-node.shape-hexagon.selected),
:deep(.custom-node.shape-trapezoid.selected) {
  border: none;
  box-shadow: none;
}

:deep(.custom-node.shape-hexagon.selected::before) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

:deep(.custom-node.shape-trapezoid.selected::before) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

/* Hover effects for shaped nodes */
:deep(.custom-node.shape-hexagon:hover::before),
:deep(.custom-node.shape-trapezoid:hover::before) {
  border-color: #999;
}

/* Override selection highlighting for other shapes that use transforms */
:deep(.custom-node.shape-circle.selected) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

:deep(.custom-node.shape-diamond.selected) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

:deep(.custom-node.shape-parallelogram.selected) {
  border-color: var(--flow-node-selected-color);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}

:deep(.custom-node-content) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:deep(.custom-node-title) {
  margin-top: 4px;
  text-align: center;
  font-weight: 500;
}

:deep(.node-gateway) {
  transform: rotate(45deg);
  background: var(--node-bg-color, white);
  border: 2px solid var(--node-border-color, #FF9800);
  color: var(--node-text-color, #333333);
}

/* Override borders for gateway shaped nodes */
:deep(.node-gateway.shape-hexagon),
:deep(.node-gateway.shape-trapezoid) {
  background: transparent;
  border: none;
}

:deep(.node-gateway .custom-node-content) {
  transform: rotate(-45deg);
}

:deep(.node-start), :deep(.node-end) {
  border-radius: 50%;
  width: 60px;
  height: 60px;
}

:deep(.node-task), :deep(.node-form), :deep(.node-script) {
  min-width: 160px;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  color: var(--node-text-color, #333333);
}

/* Override borders for shaped nodes */
:deep(.node-task.shape-hexagon), 
:deep(.node-form.shape-hexagon), 
:deep(.node-script.shape-hexagon),
:deep(.node-task.shape-trapezoid), 
:deep(.node-form.shape-trapezoid), 
:deep(.node-script.shape-trapezoid) {
  background: transparent;
  border: none;
  box-shadow: none;
}

:deep(.node-business-rule) {
  min-width: 160px;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  border-left: 4px solid var(--node-border-color, #9333ea);  /* Purple border to match our icon color */
  color: var(--node-text-color, #333333);
}

:deep(.node-notification) {
  min-width: 160px;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  border-left: 4px solid var(--node-border-color, #3b82f6);  /* Blue border to match our icon color */
  color: var(--node-text-color, #333333);
}

:deep(.node-api) {
  min-width: 160px;
  background: var(--node-bg-color, white);
  border: 1px solid var(--node-border-color, #ddd);
  border-left: 4px solid var(--node-border-color, #10b981);  /* Green border for API nodes */
  color: var(--node-text-color, #333333);
}

/* Override borders for shaped business-rule, notification, and api nodes */
:deep(.node-business-rule.shape-hexagon),
:deep(.node-business-rule.shape-trapezoid),
:deep(.node-notification.shape-hexagon),
:deep(.node-notification.shape-trapezoid),
:deep(.node-api.shape-hexagon),
:deep(.node-api.shape-trapezoid) {
  background: transparent;
  border: none;
}

:deep(.node-details) {
  margin-top: 8px;
  font-size: 0.75rem;
  width: 100%;
}

:deep(.node-description) {
  color: #666;
  margin-bottom: 4px;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.process-builder-container {
  background-color: #f8fafc;
}

.process-name-input {
  width: 100%;
  max-width: 400px;
}

.process-name-input :deep(.formkit-inner) {
  background-color: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
  color: white;
}

.process-name-input :deep(.formkit-inner:focus-within) {
  border-color: rgba(255, 255, 255, 0.5);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
}

.process-name-input :deep(input::placeholder) {
  color: rgba(255, 255, 255, 0.6);
}

.process-name-input :deep(.formkit-message) {
  color: rgba(255, 200, 200, 0.9);
  font-size: 0.7rem;
  position: absolute;
}

.process-builder-palette,
.process-builder-properties {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.process-component-item.dragging {
  opacity: 0.5;
  transform: scale(0.95);
}

.process-component-item {
  transition: all 0.2s ease;
  user-select: none;
}

.process-component-item:active {
  cursor: grabbing;
}

/* Mobile responsive adjustments */
@media (max-width: 768px) {
  .process-name-input {
    max-width: 200px;
  }
  
  .process-name-input :deep(.formkit-inner) {
    font-size: 0.875rem;
    padding: 0.5rem 0.75rem;
  }
}

/* Shape node styles */
:deep(.shape-node) {
  border-radius: 4px;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  user-select: none;
}

:deep(.shape-node.selected) {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.6);
}

/* Ensure process nodes always stay above shapes, even during drag operations */
:deep(.vue-flow__node:not([data-id*="swimlane"]):not([data-id*="rectangle-shape"]):not([data-id*="text-annotation"]):not([data-id*="process-group"]):not([data-id*="hexagon-shape"]):not([data-id*="trapezoid-shape"])) {
  z-index: 10 !important; /* Process nodes always above shapes */
}

:deep(.vue-flow__node:not([data-id*="swimlane"]):not([data-id*="rectangle-shape"]):not([data-id*="text-annotation"]):not([data-id*="process-group"]):not([data-id*="hexagon-shape"]):not([data-id*="trapezoid-shape"]).selected) {
  z-index: 15 !important; /* Selected process nodes even higher */
}

:deep(.vue-flow__node:not([data-id*="swimlane"]):not([data-id*="rectangle-shape"]):not([data-id*="text-annotation"]):not([data-id*="process-group"]):not([data-id*="hexagon-shape"]):not([data-id*="trapezoid-shape"]).dragging) {
  z-index: 20 !important; /* Dragging process nodes on top */
}

/* Vue Flow state-specific z-index rules */
:deep(.vue-flow__node[data-id*="start"]),
:deep(.vue-flow__node[data-id*="end"]),
:deep(.vue-flow__node[data-id*="form"]),
:deep(.vue-flow__node[data-id*="api"]),
:deep(.vue-flow__node[data-id*="gateway"]),
:deep(.vue-flow__node[data-id*="script"]),
:deep(.vue-flow__node[data-id*="business-rule"]),
:deep(.vue-flow__node[data-id*="notification"]) {
  z-index: 10 !important; /* All process node types above shapes */
}

:deep(.vue-flow__node[data-id*="start"].selected),
:deep(.vue-flow__node[data-id*="end"].selected),
:deep(.vue-flow__node[data-id*="form"].selected),
:deep(.vue-flow__node[data-id*="api"].selected),
:deep(.vue-flow__node[data-id*="gateway"].selected),
:deep(.vue-flow__node[data-id*="script"].selected),
:deep(.vue-flow__node[data-id*="business-rule"].selected),
:deep(.vue-flow__node[data-id*="notification"].selected) {
  z-index: 15 !important; /* Selected process nodes even higher */
}

/* Handle Vue Flow's internal dragging state classes */
:deep(.vue-flow__node.dragging:not(.shape-node)) {
  z-index: 25 !important; /* Dragging process nodes should be on top of everything */
}

/* Ensure edge connection during drag always works for process nodes */
:deep(.vue-flow.connecting .vue-flow__node:not(.shape-node)) {
  z-index: 30 !important; /* During connection mode, process nodes are highest */
}

/* Shape nodes should never interfere with edge connections */
:deep(.shape-node .vue-flow__handle) {
  display: none !important; /* Shapes should not have connection handles */
}

/* Ensure custom nodes (process nodes) maintain proper layering */
:deep(.custom-node:not(.shape-node)) {
  position: relative;
}

:deep(.custom-node:not(.shape-node).selected) {
}

/* Ensure edges/connection lines stay above shapes */
:deep(.vue-flow__edges) {
  z-index: 5 !important; /* Edges above shapes but below nodes */
}

:deep(.vue-flow__edge) {
  z-index: 5 !important; /* Individual edges above shapes */
}

:deep(.vue-flow__edge.selected) {
  z-index: 8 !important; /* Selected edges higher */
}

:deep(.vue-flow__connection) {
  z-index: 12 !important; /* Active connection line above everything except dragging nodes */
}

:deep(.vue-flow__connection-path) {
  z-index: 12 !important; /* Connection path above shapes and nodes */
}

/* Ensure edge paths and labels stay above shapes */
:deep(.vue-flow__edge-path) {
  z-index: 5 !important; /* Edge paths above shapes */
}

:deep(.vue-flow__edge-text) {
  z-index: 6 !important; /* Edge labels above edge paths and shapes */
}

:deep(.vue-flow__edge-textbg) {
  z-index: 5 !important; /* Edge text background above shapes */
}

/* Ensure SVG elements in edges maintain proper z-index */
:deep(.vue-flow__edge svg) {
  z-index: 5 !important;
}

:deep(.shape-node .shape-content) {
  padding: 8px;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:deep(.shape-node .shape-label) {
  font-weight: 500;
  line-height: 1.2;
  word-wrap: break-word;
  max-width: 100%;
}

:deep(.shape-node .shape-description) {
  font-size: 0.75rem;
  opacity: 0.8;
  margin-top: 4px;
  line-height: 1.2;
  word-wrap: break-word;
  max-width: 100%;
}

/* Specific shape styling */
:deep(.shape-node.swimlane-horizontal) {
  min-width: 600px;
  min-height: 150px;
  border-radius: 8px;
}

:deep(.shape-node.swimlane-vertical) {
  min-width: 200px;
  min-height: 400px;
  border-radius: 8px;
}

:deep(.shape-node.rectangle-shape) {
  min-width: 300px;
  min-height: 200px;
  border-radius: 4px;
}

:deep(.shape-node.text-annotation) {
  min-width: 200px;
  min-height: 80px;
  border-radius: 4px;
  font-style: italic;
}

:deep(.shape-node.process-group) {
  min-width: 400px;
  min-height: 300px;
  border-radius: 12px;
  padding: 16px;
}

:deep(.shape-node.process-group .shape-content) {
  align-items: flex-start;
  justify-content: flex-start;
}

/* Touch-friendly adjustments */
@media (hover: none) and (pointer: coarse) {
  .component-item {
    min-height: 44px; /* iOS touch target minimum */
  }
  
  .dropdown-menu button {
    min-height: 44px;
    padding: 0.75rem 1rem;
  }
  
  /* Larger tap targets for mobile */
  .process-builder :deep(.vue-flow__node) {
    min-width: 120px;
    min-height: 40px;
  }
  
  .process-builder :deep(.vue-flow__handle) {
    width: 12px;
    height: 12px;
  }
}

/* Panel transitions and animations */
.panel-enter-active,
.panel-leave-active {
  transition: transform 0.3s ease-in-out;
}

.panel-enter-from {
  transform: translateX(-100%);
}

.panel-leave-to {
  transform: translateX(-100%);
}

.panel-right-enter-from {
  transform: translateX(100%);
}

.panel-right-leave-to {
  transform: translateX(100%);
}

/* Improved mobile canvas interactions */
@media (max-width: 768px) {
  .process-builder :deep(.vue-flow__pane) {
    touch-action: pan-x pan-y;
  }
  
  .process-builder :deep(.vue-flow__node) {
    cursor: pointer;
  }
  
  .process-builder :deep(.vue-flow__edge) {
    pointer-events: stroke;
    stroke-width: 3px; /* Thicker edges for easier mobile selection */
  }
}

/* Modern icon button style for node actions */
.modern-icon-btn {
  padding: 0.375rem;
  border-radius: 9999px;
  min-width: 32px;
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}
.modern-icon-btn:hover {
  background: #f3f4f6;
}
.modern-icon-btn[variant~='danger-text']:hover {
  background: #fee2e2;
}

/* Ensure full canvas coverage */
.process-builder {
  height: 100vh;
  overflow: hidden;
}

/* Override Vue Flow container to fill full height */
:deep(.vue-flow) {
  width: 100% !important;
  height: 100% !important;
  min-height: 100% !important;
}

:deep(.vue-flow__pane) {
  width: 100% !important;
  height: 100% !important;
}

:deep(.vue-flow__renderer) {
  width: 100% !important;
  height: 100% !important;
}
</style> 