import { jsx, jsxs } from "react/jsx-runtime";
import styled from "@emotion/styled";
import { Column } from "../../layouts/index.js";
import { Panel, useReactFlow } from "../../xyflow/react.js";
import { StickyNote } from "lucide-react";
import { memo, useCallback, useEffect, useMemo, useRef } from "react";
import { BaseCanvas } from "../BaseCanvas/index.js";
import { DefaultAgentNodeTranslations, DefaultCanvasTranslations, DefaultResourceNodeTranslations, DefaultStickyNoteNodeTranslations, DefaultSuggestionTranslations, isAgentFlowAgentNode, isAgentFlowResourceNode, isStickyNoteNode } from "../../types.js";
import { hasAgentRunning } from "../../utils/props-helpers.js";
import { CanvasPositionControls } from "../CanvasPositionControls.js";
import { StickyNoteNode } from "../StickyNoteNode/index.js";
import { PaneContextMenu } from "./components/PaneContextMenu.js";
import { SuggestionGroupPanel } from "./components/SuggestionGroupPanel.js";
import { TimelinePlayer } from "./components/TimelinePlayer.js";
import { calculateTimelineHeight } from "./components/TimelinePlayer.utils.js";
import { Edge } from "./edges/Edge.js";
import { AgentNodeElement } from "./nodes/AgentNode.js";
import { ResourceNode } from "./nodes/ResourceNode.js";
import { AgentFlowProvider, useAgentFlowStore } from "./store/agent-flow-store.js";
import { NodeRegistryProvider } from "../../core/NodeRegistryProvider.js";
import { agentFlowManifest } from "./agent-flow.manifest.js";
const ToolbarContainer = styled.div`
  display: flex;
  align-items: center;
  background: var(--canvas-background);
  border: 1px solid var(--canvas-border-de-emp);
  border-radius: 16px;
  padding: 4px;
  gap: 4px;
  height: 50px;
`;
const ToolbarButton = styled.button`
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  border-radius: 16px;
  transition: background-color 0.15s ease;
  color: var(--canvas-foreground);

  &:hover {
    background: var(--canvas-background-hover);
  }
`;
const edgeTypes = {
    default: Edge
};
const AGENT_FLOW_FIT_VIEW_OPTIONS = {
    padding: {
        top: 0.3,
        right: 0.3,
        bottom: 0.3,
        left: 0.3
    },
    duration: 300
};
const createAgentNodeWrapper = (handlers)=>(props)=>{
        const { props: storeProps, nodes, setSelectedNodeId } = useAgentFlowStore();
        const hasContext = nodes.some((node)=>isAgentFlowResourceNode(node) && 'context' === node.data.type && node.data.parentNodeId === props.id);
        const hasEscalation = nodes.some((node)=>isAgentFlowResourceNode(node) && 'escalation' === node.data.type && node.data.parentNodeId === props.id);
        const hasTool = nodes.some((node)=>isAgentFlowResourceNode(node) && 'tool' === node.data.type && node.data.parentNodeId === props.id);
        const hasMcp = false !== handlers.enableMcpTools && nodes.some((node)=>isAgentFlowResourceNode(node) && 'mcp' === node.data.type && node.data.parentNodeId === props.id);
        const hasMemory = nodes.some((node)=>isAgentFlowResourceNode(node) && 'memorySpace' === node.data.type && node.data.parentNodeId === props.id);
        const hasA2a = true === handlers.enableA2a && nodes.some((node)=>isAgentFlowResourceNode(node) && 'a2a' === node.data.type && node.data.parentNodeId === props.id);
        const agentRunning = hasAgentRunning(storeProps.spans);
        const resourceRunning = nodes.some((node)=>isAgentFlowResourceNode(node) && 'view' === storeProps.mode && node.data.parentNodeId === props.id && node.data.hasRunning);
        const agentProcessing = props.data.isProcessing;
        const hasRunning = agentRunning || resourceRunning || agentProcessing;
        const hasError = !hasRunning && nodes.some((node)=>isAgentFlowResourceNode(node) && node.data.parentNodeId === props.id && node.data.hasError);
        const hasSuccess = !hasRunning && nodes.some((node)=>isAgentFlowResourceNode(node) && node.data.parentNodeId === props.id && node.data.hasSuccess);
        const handleAddInstructions = useCallback(()=>{
            setSelectedNodeId(props.id);
            storeProps.onSelectResource?.(props.id);
        }, [
            setSelectedNodeId,
            storeProps.onSelectResource,
            props.id
        ]);
        return /*#__PURE__*/ jsx(AgentNodeElement, {
            ...props,
            hasContext: hasContext,
            hasEscalation: hasEscalation,
            hasTool: hasTool,
            hasMcp: hasMcp,
            hasMemory: hasMemory,
            hasA2a: hasA2a,
            a2aEnabled: true === handlers.enableA2a,
            mcpEnabled: false !== handlers.enableMcpTools,
            mode: storeProps.mode,
            hasError: hasError,
            hasSuccess: hasSuccess,
            hasRunning: hasRunning,
            onAddResource: handlers.onAddResource,
            onAddInstructions: handleAddInstructions,
            translations: handlers.translations ?? DefaultAgentNodeTranslations,
            suggestionTranslations: handlers.suggestionTranslations ?? DefaultSuggestionTranslations,
            enableMemory: true === handlers.enableMemory,
            enableInstructions: true === handlers.enableInstructions,
            healthScore: handlers.healthScore,
            onHealthScoreClick: handlers.onHealthScoreClick,
            suggestionGroupVersion: handlers.suggestionGroupVersion
        });
    };
const createResourceNodeWrapper = (opts)=>(props)=>{
        const { props: storeProps, deleteNode } = useAgentFlowStore();
        return /*#__PURE__*/ jsx(ResourceNode, {
            ...props,
            mode: storeProps.mode,
            hasError: props.data.hasError,
            hasSuccess: props.data.hasSuccess,
            hasRunning: props.data.hasRunning,
            onEnable: opts.onEnable,
            onDisable: opts.onDisable,
            onAddBreakpoint: opts.onAddBreakpoint,
            onRemoveBreakpoint: opts.onRemoveBreakpoint,
            onAddGuardrail: opts.onAddGuardrail,
            onGoToSource: opts.onGoToSource,
            onErrorAction: opts.onErrorAction,
            onRemoveResource: deleteNode,
            onExpandResource: opts.onExpandResource,
            onCollapseResource: opts.onCollapseResource,
            translations: opts.translations ?? DefaultResourceNodeTranslations,
            suggestionTranslations: opts.suggestionTranslations ?? DefaultSuggestionTranslations,
            suggestionGroupVersion: opts.suggestionGroupVersion
        });
    };
const AgentFlowInner = /*#__PURE__*/ memo(({ children, mode, spans, onEnable, onDisable, onAddBreakpoint, onRemoveBreakpoint, onAddGuardrail, onGoToSource, onErrorAction, onAddResource: _onAddResource, onSelectResource, setSpanForSelectedNode, getNodeFromSelectedSpan, onExpandResource, onCollapseResource, agentNodeTranslations, resourceNodeTranslations, stickyNoteNodeTranslations, canvasTranslations, enableTimelinePlayer, canvasRef, enableMcpTools, enableMemory, enableA2a, enableStickyNotes, enableInstructions, healthScore, onHealthScoreClick, suggestionTranslations, suggestionGroup, onAgentNodePositionChange, onResourceNodePositionChange, onOrganize, onUpdateStickyNote, zoomLevel, onZoomLevelChange })=>{
    const { nodes, edges, onNodesChange, onEdgesChange, onConnect, autoArrange, setSelectedNodeId, selectedNodeId, setDragging, expandAgent, collapseAgent, createResourcePlaceholder, actOnSuggestionGroup, currentSuggestionIndex, navigateToNextSuggestion, navigateToPreviousSuggestion, addStickyNote, paneContextMenu, openPaneContextMenu, closePaneContextMenu } = useAgentFlowStore();
    const nodeTypesBase = useMemo(()=>({
            stickyNote: (props)=>/*#__PURE__*/ jsx(StickyNoteNode, {
                    ...props,
                    placeholder: (stickyNoteNodeTranslations ?? DefaultStickyNoteNodeTranslations).placeholder,
                    renderPlaceholderOnSelect: true
                })
        }), [
        stickyNoteNodeTranslations
    ]);
    const { fitView: reactFlowFitView, screenToFlowPosition: reactFlowScreenToFlowPosition } = useReactFlow();
    const timelinePlayerRef = useRef(null);
    const suggestionGroupPanelRef = useRef(null);
    const toolbarContainerRef = useRef(null);
    const timelineHeight = useMemo(()=>calculateTimelineHeight(enableTimelinePlayer, spans), [
        enableTimelinePlayer,
        spans
    ]);
    const suggestionGroupPanelHeight = suggestionGroupPanelRef.current?.offsetHeight || 0;
    const toolbarContainerHeight = toolbarContainerRef.current?.offsetHeight || 0;
    const adjustedFitViewOptions = useMemo(()=>{
        if ([
            timelineHeight,
            suggestionGroupPanelHeight,
            toolbarContainerHeight
        ].some((height)=>height > 0)) {
            const viewportHeight = window.innerHeight;
            const timelineRatio = timelineHeight / viewportHeight;
            const suggestionGroupPanelRatio = suggestionGroupPanelHeight / viewportHeight;
            const toolbarContainerRatio = toolbarContainerHeight / viewportHeight;
            const bottomPadding = AGENT_FLOW_FIT_VIEW_OPTIONS.padding.bottom + 3 * (timelineRatio + suggestionGroupPanelRatio + toolbarContainerRatio);
            return {
                ...AGENT_FLOW_FIT_VIEW_OPTIONS,
                padding: {
                    ...AGENT_FLOW_FIT_VIEW_OPTIONS.padding,
                    bottom: bottomPadding
                }
            };
        }
        return AGENT_FLOW_FIT_VIEW_OPTIONS;
    }, [
        timelineHeight,
        suggestionGroupPanelHeight,
        toolbarContainerHeight
    ]);
    const nodeTypes = useMemo(()=>{
        const handleAddResource = (type)=>{
            createResourcePlaceholder(type);
        };
        const suggestionGroupVersion = suggestionGroup?.metadata?.version;
        return {
            ...nodeTypesBase,
            agent: createAgentNodeWrapper({
                onAddResource: handleAddResource,
                translations: agentNodeTranslations,
                suggestionTranslations,
                enableMcpTools,
                enableMemory,
                enableA2a,
                enableInstructions,
                healthScore,
                onHealthScoreClick,
                suggestionGroupVersion
            }),
            resource: createResourceNodeWrapper({
                onEnable,
                onDisable,
                onAddBreakpoint,
                onRemoveBreakpoint,
                onAddGuardrail,
                onGoToSource,
                onErrorAction,
                onExpandResource,
                onCollapseResource,
                translations: resourceNodeTranslations,
                suggestionTranslations,
                suggestionGroupVersion
            })
        };
    }, [
        onEnable,
        onDisable,
        onAddBreakpoint,
        onRemoveBreakpoint,
        onAddGuardrail,
        onGoToSource,
        onErrorAction,
        healthScore,
        onHealthScoreClick,
        createResourcePlaceholder,
        agentNodeTranslations,
        resourceNodeTranslations,
        suggestionTranslations,
        onExpandResource,
        onCollapseResource,
        enableMcpTools,
        enableMemory,
        suggestionGroup?.metadata?.version
    ]);
    const handlePaneClick = useCallback(()=>{
        setSelectedNodeId(null);
        onSelectResource?.('pane');
        closePaneContextMenu();
    }, [
        onSelectResource,
        setSelectedNodeId,
        closePaneContextMenu
    ]);
    const handleNodeClick = useCallback((_event, node)=>{
        _event.stopPropagation();
        _event.preventDefault();
        setSelectedNodeId(node.id);
        setSpanForSelectedNode?.(node, nodes);
        onSelectResource?.(node.id);
    }, [
        onSelectResource,
        setSelectedNodeId,
        setSpanForSelectedNode,
        nodes
    ]);
    const handleNodeContextMenu = useCallback((event, node)=>{
        event.stopPropagation();
        event.preventDefault();
        setSelectedNodeId(node.id);
        setSpanForSelectedNode?.(node, nodes);
        onSelectResource?.(node.id);
    }, [
        onSelectResource,
        setSelectedNodeId,
        setSpanForSelectedNode,
        nodes
    ]);
    const handlePaneContextMenu = useCallback((event)=>{
        event.stopPropagation();
        event.preventDefault();
        const screenPosition = {
            x: event.clientX,
            y: event.clientY
        };
        const flowPosition = reactFlowScreenToFlowPosition(screenPosition);
        openPaneContextMenu(screenPosition, flowPosition);
    }, [
        openPaneContextMenu,
        reactFlowScreenToFlowPosition
    ]);
    const handleNodeDragStart = useCallback((_event, node)=>{
        setSelectedNodeId(node.id);
        onSelectResource?.(node.id);
        if (!isAgentFlowResourceNode(node)) return;
        setDragging(true, node.id);
    }, [
        setSelectedNodeId,
        onSelectResource,
        setDragging
    ]);
    const handleNodeDragStop = useCallback((_event, node)=>{
        if (isStickyNoteNode(node)) return void onUpdateStickyNote?.(node.id, {
            position: {
                x: node.position.x,
                y: node.position.y
            }
        });
        if (!isAgentFlowResourceNode(node)) return void onAgentNodePositionChange?.({
            x: node.position.x,
            y: node.position.y
        });
        const agentNode = nodes.find(isAgentFlowAgentNode);
        if (agentNode) onAgentNodePositionChange?.({
            x: agentNode.position.x,
            y: agentNode.position.y
        });
        onResourceNodePositionChange?.(node.id, {
            x: node.position.x,
            y: node.position.y
        });
    }, [
        onAgentNodePositionChange,
        onResourceNodePositionChange,
        onUpdateStickyNote,
        nodes
    ]);
    useEffect(()=>{
        const handleExpandAgent = (event)=>{
            const customEvent = event;
            const { resourceId, agentDetails } = customEvent.detail;
            expandAgent(resourceId, agentDetails);
        };
        window.addEventListener('expandAgent', handleExpandAgent);
        return ()=>{
            window.removeEventListener('expandAgent', handleExpandAgent);
        };
    }, [
        expandAgent
    ]);
    useEffect(()=>{
        const handleCollapseAgent = (event)=>{
            const customEvent = event;
            const { resourceId } = customEvent.detail;
            collapseAgent(resourceId);
        };
        window.addEventListener('collapseAgent', handleCollapseAgent);
        return ()=>{
            window.removeEventListener('collapseAgent', handleCollapseAgent);
        };
    }, [
        collapseAgent
    ]);
    useEffect(()=>{
        const handleResetSelectedNode = ()=>{
            setSelectedNodeId(null);
            onSelectResource?.(null);
            reactFlowFitView(adjustedFitViewOptions);
        };
        window.addEventListener('resetSelectedNode', handleResetSelectedNode);
        return ()=>{
            window.removeEventListener('resetSelectedNode', handleResetSelectedNode);
        };
    }, [
        setSelectedNodeId,
        onSelectResource,
        reactFlowFitView,
        adjustedFitViewOptions
    ]);
    useEffect(()=>{
        if (0 === nodes.length || 0 === spans.length) return;
        const targetNode = getNodeFromSelectedSpan?.(nodes);
        if (targetNode && targetNode?.id !== selectedNodeId) {
            setSelectedNodeId(targetNode.id);
            onSelectResource?.(targetNode.id);
        }
    }, [
        nodes,
        setSelectedNodeId,
        onSelectResource,
        getNodeFromSelectedSpan,
        selectedNodeId,
        spans
    ]);
    const filteredNodes = nodes.filter((node)=>{
        if (!isAgentFlowResourceNode(node)) return true;
        if (node.data.isVirtual) return true;
        if ('memorySpace' === node.data.type) return !!enableMemory;
        if ('a2a' === node.data.type) return !!enableA2a;
        return true;
    });
    const defaultViewport = useMemo(()=>{
        if (void 0 !== zoomLevel) return {
            x: 0,
            y: 0,
            zoom: zoomLevel
        };
    }, [
        zoomLevel
    ]);
    const handleViewportChange = useCallback((_event, viewport)=>{
        const newZoomLevel = Math.round(100 * viewport.zoom) / 100;
        const currentZoomLevel = zoomLevel ? Math.round(100 * zoomLevel) / 100 : void 0;
        if (onZoomLevelChange && newZoomLevel !== currentZoomLevel) onZoomLevelChange(newZoomLevel);
    }, [
        onZoomLevelChange,
        zoomLevel
    ]);
    return /*#__PURE__*/ jsx(Column, {
        w: "100%",
        h: "100%",
        style: {
            touchAction: 'none'
        },
        children: /*#__PURE__*/ jsxs(Column, {
            flex: 1,
            position: "relative",
            style: {
                touchAction: 'none'
            },
            children: [
                /*#__PURE__*/ jsxs(BaseCanvas, {
                    ref: canvasRef,
                    nodes: filteredNodes,
                    edges: edges,
                    nodeTypes: nodeTypes,
                    edgeTypes: edgeTypes,
                    mode: mode,
                    initialAutoLayout: autoArrange,
                    fitViewOptions: adjustedFitViewOptions,
                    defaultViewport: defaultViewport,
                    onMove: handleViewportChange,
                    onNodesChange: onNodesChange,
                    onEdgesChange: onEdgesChange,
                    onConnect: onConnect,
                    onNodeClick: handleNodeClick,
                    onNodeContextMenu: handleNodeContextMenu,
                    onPaneContextMenu: handlePaneContextMenu,
                    onPaneClick: handlePaneClick,
                    onNodeDragStart: handleNodeDragStart,
                    onNodeDragStop: handleNodeDragStop,
                    deleteKeyCode: 'design' === mode ? [
                        'Backspace',
                        'Delete'
                    ] : null,
                    maintainNodesInView: [],
                    panShortcutTeachingUIMessage: (canvasTranslations ?? DefaultCanvasTranslations).panShortcutTeaching,
                    children: [
                        /*#__PURE__*/ jsx(Panel, {
                            position: "bottom-right",
                            children: /*#__PURE__*/ jsx(CanvasPositionControls, {
                                fitViewOptions: adjustedFitViewOptions,
                                translations: canvasTranslations ?? DefaultCanvasTranslations,
                                onOrganize: 'design' === mode ? onOrganize : void 0
                            })
                        }),
                        /*#__PURE__*/ jsxs(Panel, {
                            position: "bottom-center",
                            children: [
                                /*#__PURE__*/ jsx("div", {
                                    ref: timelinePlayerRef,
                                    children: /*#__PURE__*/ jsx(TimelinePlayer, {
                                        spans: spans ?? [],
                                        enableTimelinePlayer: enableTimelinePlayer ?? true
                                    })
                                }),
                                /*#__PURE__*/ jsx("div", {
                                    ref: toolbarContainerRef,
                                    children: enableStickyNotes && 'design' === mode && !suggestionGroup?.suggestions.length && /*#__PURE__*/ jsx(ToolbarContainer, {
                                        className: "nodrag nopan nowheel",
                                        children: /*#__PURE__*/ jsx(ToolbarButton, {
                                            type: "button",
                                            onClick: ()=>addStickyNote(),
                                            title: (canvasTranslations ?? DefaultCanvasTranslations).addNote,
                                            children: /*#__PURE__*/ jsx(StickyNote, {
                                                size: 16
                                            })
                                        })
                                    })
                                }),
                                /*#__PURE__*/ jsx("div", {
                                    ref: suggestionGroupPanelRef,
                                    children: /*#__PURE__*/ jsx(SuggestionGroupPanel, {
                                        suggestionGroup: suggestionGroup,
                                        onRejectAll: (suggestionGroupId)=>actOnSuggestionGroup?.(suggestionGroupId, 'reject'),
                                        onAcceptAll: (suggestionGroupId)=>actOnSuggestionGroup?.(suggestionGroupId, 'accept'),
                                        currentIndex: currentSuggestionIndex,
                                        onNavigateNext: navigateToNextSuggestion,
                                        onNavigatePrevious: navigateToPreviousSuggestion
                                    })
                                })
                            ]
                        }),
                        children
                    ]
                }),
                'design' === mode && /*#__PURE__*/ jsx(PaneContextMenu, {
                    isOpen: null !== paneContextMenu,
                    position: paneContextMenu?.position ?? {
                        x: 0,
                        y: 0
                    },
                    items: [
                        ...enableStickyNotes ? [
                            {
                                label: (canvasTranslations ?? DefaultCanvasTranslations).addNote,
                                onClick: ()=>addStickyNote({
                                        position: paneContextMenu?.flowPosition ?? {
                                            x: 0,
                                            y: 0
                                        }
                                    })
                            }
                        ] : [],
                        ...onOrganize ? [
                            {
                                label: (canvasTranslations ?? DefaultCanvasTranslations).organize,
                                onClick: onOrganize
                            }
                        ] : []
                    ],
                    onClose: closePaneContextMenu
                })
            ]
        })
    });
});
AgentFlowInner.displayName = 'AgentFlowInner';
const AgentFlow = (props)=>/*#__PURE__*/ jsx(NodeRegistryProvider, {
        manifest: agentFlowManifest,
        children: /*#__PURE__*/ jsx(AgentFlowProvider, {
            ...props,
            children: /*#__PURE__*/ jsx(AgentFlowInner, {
                ...props
            })
        })
    });
export { AgentFlow };
