import { useState, useMemo, useCallback, useEffect } from 'react';

// src/graph/constants.ts
var GRAPH_CONSTANTS = {
  NODE_WIDTH: 220,
  NODE_HEIGHT: 140,
  HANDLE_SIZE: 12,
  MIN_ZOOM: 0.2,
  MAX_ZOOM: 1.5,
  RANK_SEP: 140,
  NODE_SEP: 60
};
function useConnectionHighlight(nodes, edges) {
  const [hoveredNodeId, setHoveredNodeId] = useState(null);
  const adjacencyMap = useMemo(() => {
    const map = /* @__PURE__ */ new Map();
    for (const node of nodes) {
      map.set(node.id, { connectedNodes: /* @__PURE__ */ new Set(), connectedEdges: /* @__PURE__ */ new Set() });
    }
    for (const edge of edges) {
      const sourceData = map.get(edge.source);
      const targetData = map.get(edge.target);
      if (sourceData) {
        sourceData.connectedNodes.add(edge.target);
        sourceData.connectedEdges.add(edge.id);
      }
      if (targetData) {
        targetData.connectedNodes.add(edge.source);
        targetData.connectedEdges.add(edge.id);
      }
    }
    return map;
  }, [nodes, edges]);
  const { highlightedNodeIds, highlightedEdgeIds } = useMemo(() => {
    if (!hoveredNodeId) {
      return {
        highlightedNodeIds: /* @__PURE__ */ new Set(),
        highlightedEdgeIds: /* @__PURE__ */ new Set()
      };
    }
    const nodeData = adjacencyMap.get(hoveredNodeId);
    if (!nodeData) {
      return {
        highlightedNodeIds: /* @__PURE__ */ new Set(),
        highlightedEdgeIds: /* @__PURE__ */ new Set()
      };
    }
    const highlightedNodes = /* @__PURE__ */ new Set([hoveredNodeId, ...Array.from(nodeData.connectedNodes)]);
    return {
      highlightedNodeIds: highlightedNodes,
      highlightedEdgeIds: nodeData.connectedEdges
    };
  }, [hoveredNodeId, adjacencyMap]);
  const onNodeMouseEnter = useCallback((nodeId) => {
    setHoveredNodeId(nodeId);
  }, []);
  const onNodeMouseLeave = useCallback(() => {
    setHoveredNodeId(null);
  }, []);
  const getNodeClassName = useCallback(
    (nodeId) => {
      if (!hoveredNodeId) return "";
      if (highlightedNodeIds.has(nodeId)) return "nodeHighlighted";
      return "nodeDimmed";
    },
    [hoveredNodeId, highlightedNodeIds]
  );
  const getEdgeClassName = useCallback(
    (edgeId) => {
      if (!hoveredNodeId) return "";
      if (highlightedEdgeIds.has(edgeId)) return "edgeHighlighted";
      return "edgeDimmed";
    },
    [hoveredNodeId, highlightedEdgeIds]
  );
  return {
    hoveredNodeId,
    highlightedNodeIds,
    highlightedEdgeIds,
    onNodeMouseEnter,
    onNodeMouseLeave,
    getNodeClassName,
    getEdgeClassName
  };
}

// src/graph/Graph.module.css.js
var Graph_module_css_default = { "livePulse": "livePulse", "graphContainer": "graphContainer", "node": "node", "nodeCard": "nodeCard", "nodeCardSelected": "nodeCardSelected", "nodeAgent": "nodeAgent", "nodeWorkflow": "nodeWorkflow", "nodeTrigger": "nodeTrigger", "nodeIntegration": "nodeIntegration", "nodeExternal": "nodeExternal", "nodeHuman": "nodeHuman", "nodePrimary": "nodePrimary", "handle": "handle", "nodeIcon": "nodeIcon", "badge": "badge", "badgeProd": "badgeProd", "edge": "edge", "edgeAnimated": "edgeAnimated", "edgeGlow": "edgeGlow", "edgeHighlighted": "edgeHighlighted", "edgeLabel": "edgeLabel", "legend": "legend", "legendDot": "legendDot", "nodeHighlighted": "nodeHighlighted", "nodeDimmed": "nodeDimmed", "edgeDimmed": "edgeDimmed", "edgeLabelDimmed": "edgeLabelDimmed" };

// src/graph/hooks/useGraphHighlighting.ts
function useGraphHighlighting(layoutNodes, layoutEdges) {
  const {
    hoveredNodeId,
    highlightedNodeIds,
    highlightedEdgeIds,
    onNodeMouseEnter,
    onNodeMouseLeave
  } = useConnectionHighlight(layoutNodes, layoutEdges);
  const nodes = useMemo(() => {
    return layoutNodes.map((node) => ({
      ...node,
      className: hoveredNodeId ? highlightedNodeIds.has(node.id) ? Graph_module_css_default.nodeHighlighted : Graph_module_css_default.nodeDimmed : ""
    }));
  }, [layoutNodes, hoveredNodeId, highlightedNodeIds]);
  const edges = useMemo(() => {
    return layoutEdges.map((edge) => {
      const isDimmed = hoveredNodeId ? !highlightedEdgeIds.has(edge.id) : false;
      return {
        ...edge,
        className: hoveredNodeId ? highlightedEdgeIds.has(edge.id) ? Graph_module_css_default.edgeHighlighted : Graph_module_css_default.edgeDimmed : "",
        data: {
          ...edge.data,
          dimmed: isDimmed
        }
      };
    });
  }, [layoutEdges, hoveredNodeId, highlightedEdgeIds]);
  const handleNodeMouseEnter = useCallback(
    (_event, node) => onNodeMouseEnter(node.id),
    [onNodeMouseEnter]
  );
  const handleNodeMouseLeave = useCallback(() => {
    onNodeMouseLeave();
  }, [onNodeMouseLeave]);
  return {
    nodes,
    edges,
    handleNodeMouseEnter,
    handleNodeMouseLeave
  };
}
function useDirectedChainHighlighting(layoutNodes, layoutEdges, options = {}) {
  const { selectedNodeId } = options;
  const [hoveredNodeId, setHoveredNodeId] = useState(null);
  const reachabilityMap = useMemo(() => {
    const map = /* @__PURE__ */ new Map();
    const forwardAdj = /* @__PURE__ */ new Map();
    const backwardAdj = /* @__PURE__ */ new Map();
    for (const node of layoutNodes) {
      forwardAdj.set(node.id, { nodes: /* @__PURE__ */ new Set(), edges: /* @__PURE__ */ new Set() });
      backwardAdj.set(node.id, { nodes: /* @__PURE__ */ new Set(), edges: /* @__PURE__ */ new Set() });
    }
    for (const edge of layoutEdges) {
      const sourceForward = forwardAdj.get(edge.source);
      if (sourceForward) {
        sourceForward.nodes.add(edge.target);
        sourceForward.edges.add(edge.id);
      }
      const targetBackward = backwardAdj.get(edge.target);
      if (targetBackward) {
        targetBackward.nodes.add(edge.source);
        targetBackward.edges.add(edge.id);
      }
    }
    const traverse = (startId, adjacency) => {
      const reachableNodes = /* @__PURE__ */ new Set();
      const reachableEdges = /* @__PURE__ */ new Set();
      const queue = [startId];
      while (queue.length > 0) {
        const currentId = queue.shift();
        if (reachableNodes.has(currentId)) continue;
        reachableNodes.add(currentId);
        const adj = adjacency.get(currentId);
        if (adj) {
          Array.from(adj.edges).forEach((edgeId) => {
            reachableEdges.add(edgeId);
          });
          Array.from(adj.nodes).forEach((neighborId) => {
            if (!reachableNodes.has(neighborId)) {
              queue.push(neighborId);
            }
          });
        }
      }
      return { nodes: reachableNodes, edges: reachableEdges };
    };
    for (const node of layoutNodes) {
      const successors = traverse(node.id, forwardAdj);
      const predecessors = traverse(node.id, backwardAdj);
      const allNodes = /* @__PURE__ */ new Set([node.id]);
      Array.from(successors.nodes).forEach((id) => allNodes.add(id));
      Array.from(predecessors.nodes).forEach((id) => allNodes.add(id));
      const allEdges = /* @__PURE__ */ new Set();
      Array.from(successors.edges).forEach((id) => allEdges.add(id));
      Array.from(predecessors.edges).forEach((id) => allEdges.add(id));
      map.set(node.id, { nodeIds: allNodes, edgeIds: allEdges });
    }
    return map;
  }, [layoutNodes, layoutEdges]);
  const { highlightedNodeIds, highlightedEdgeIds, hasHighlight } = useMemo(() => {
    const nodeIds = /* @__PURE__ */ new Set();
    const edgeIds = /* @__PURE__ */ new Set();
    if (selectedNodeId) {
      const selectedReachability = reachabilityMap.get(selectedNodeId);
      if (selectedReachability) {
        selectedReachability.nodeIds.forEach((id) => nodeIds.add(id));
        selectedReachability.edgeIds.forEach((id) => edgeIds.add(id));
      }
    }
    if (hoveredNodeId) {
      const hoveredReachability = reachabilityMap.get(hoveredNodeId);
      if (hoveredReachability) {
        hoveredReachability.nodeIds.forEach((id) => nodeIds.add(id));
        hoveredReachability.edgeIds.forEach((id) => edgeIds.add(id));
      }
    }
    return {
      highlightedNodeIds: nodeIds,
      highlightedEdgeIds: edgeIds,
      hasHighlight: nodeIds.size > 0
    };
  }, [selectedNodeId, hoveredNodeId, reachabilityMap]);
  const nodes = useMemo(() => {
    return layoutNodes.map((node) => {
      const isHighlighted = hasHighlight ? highlightedNodeIds.has(node.id) : false;
      const isDimmed = hasHighlight ? !highlightedNodeIds.has(node.id) : false;
      return {
        ...node,
        className: isDimmed ? Graph_module_css_default.nodeDimmed : "",
        data: {
          ...node.data,
          highlighted: isHighlighted
        }
      };
    });
  }, [layoutNodes, hasHighlight, highlightedNodeIds]);
  const edges = useMemo(() => {
    return layoutEdges.map((edge) => {
      const isDimmed = hasHighlight ? !highlightedEdgeIds.has(edge.id) : false;
      return {
        ...edge,
        className: hasHighlight ? highlightedEdgeIds.has(edge.id) ? Graph_module_css_default.edgeHighlighted : Graph_module_css_default.edgeDimmed : "",
        data: {
          ...edge.data,
          dimmed: isDimmed
        }
      };
    });
  }, [layoutEdges, hasHighlight, highlightedEdgeIds]);
  const handleNodeMouseEnter = useCallback(
    (_event, node) => setHoveredNodeId(node.id),
    []
  );
  const handleNodeMouseLeave = useCallback(() => {
    setHoveredNodeId(null);
  }, []);
  return {
    nodes,
    edges,
    hoveredNodeId,
    handleNodeMouseEnter,
    handleNodeMouseLeave
  };
}
function useNodeSelection(selectedId, onSelect) {
  const handleNodeClick = useCallback(
    (event, node) => {
      event.stopPropagation();
      const nodeId = node.id;
      if (selectedId === nodeId) {
        onSelect(null);
      } else {
        onSelect(nodeId);
      }
    },
    [selectedId, onSelect]
  );
  const handlePaneClick = useCallback(() => {
    if (selectedId !== null) {
      onSelect(null);
    }
  }, [selectedId, onSelect]);
  const handleContainerClick = useCallback(
    (event) => {
      if (event.target === event.currentTarget) {
        onSelect(null);
      }
    },
    [onSelect]
  );
  return {
    handleNodeClick,
    handlePaneClick,
    handleContainerClick
  };
}
function useFitViewTrigger(data, nodes) {
  const [fitViewTrigger, setFitViewTrigger] = useState(0);
  useEffect(() => {
    if (data) {
      setFitViewTrigger((prev) => prev + 1);
    }
  }, [data]);
  useEffect(() => {
    if (nodes.length > 0) {
      setFitViewTrigger((prev) => prev + 1);
    }
  }, [nodes]);
  return fitViewTrigger;
}

// src/graph/utils/calculateGraphHeight.ts
function calculateGraphHeight({
  itemCount,
  minHeight = 300,
  maxHeight = 500,
  heightPerItem = 80
}) {
  const calculated = minHeight + itemCount * heightPerItem;
  return Math.min(calculated, maxHeight);
}

export { GRAPH_CONSTANTS, Graph_module_css_default, calculateGraphHeight, useConnectionHighlight, useDirectedChainHighlighting, useFitViewTrigger, useGraphHighlighting, useNodeSelection };
