import { jsx, jsxs } from "react/jsx-runtime";
import styled from "@emotion/styled";
import { Spacing } from "@uipath/apollo-core";
import { AgentIcon, CodedAgentIcon } from "../../icons/index.js";
import { Row } from "../../layouts/index.js";
import { BaseEdge, Panel, Position, ReactFlowProvider, getSimpleBezierPath, useEdgesState, useNodesState, useReactFlow } from "../../xyflow/react.js";
import { Spinner } from "@uipath/apollo-wind";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { NodeRegistryProvider } from "../../core/NodeRegistryProvider.js";
import { DefaultCanvasTranslations, DefaultCodedAgentNodeTranslations } from "../../types.js";
import { d3HierarchyLayout } from "../../utils/coded-agents/d3-layout.js";
import { mermaidToReactFlow } from "../../utils/coded-agents/mermaid-parser.js";
import { CanvasIcon } from "../../utils/icon-registry.js";
import { BaseCanvas } from "../BaseCanvas/index.js";
import { BaseNode } from "../BaseNode/BaseNode.js";
import { BaseNodeOverrideConfigProvider } from "../BaseNode/BaseNodeConfigContext.js";
import { CanvasPositionControls } from "../CanvasPositionControls.js";
import { codedAgentManifest } from "./coded-agent.manifest.js";
const LAYOUT_SPACING = [
    110,
    80
];
const CodedAgentEdge = /*#__PURE__*/ memo(({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style, markerEnd, animated })=>{
    const [edgePath] = getSimpleBezierPath({
        sourceX,
        sourceY,
        sourcePosition,
        targetX,
        targetY,
        targetPosition
    });
    const strokeColor = animated ? 'var(--canvas-primary)' : 'var(--canvas-foreground-de-emp)';
    return /*#__PURE__*/ jsx(BaseEdge, {
        id: id,
        path: edgePath,
        markerEnd: markerEnd,
        style: {
            ...style,
            stroke: strokeColor,
            strokeWidth: 1,
            transition: 'stroke 0.2s ease-in-out'
        }
    });
});
const CenteredDiv = styled.div`
  background-color: var(--canvas-background-secondary);
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
`;
const TextContainer = styled.div`
  position: absolute;
  bottom: 0;
  transform: translateY(100%);
  text-align: center;
  white-space: nowrap;
`;
const leftTargetHandle = [
    {
        id: 'left',
        type: 'target',
        handleType: 'artifact',
        showButton: false
    }
];
const rightSourceHandle = [
    {
        id: 'right',
        type: 'source',
        handleType: 'artifact',
        showButton: false
    }
];
const rightOutputHandle = [
    {
        id: 'right',
        type: 'source',
        handleType: 'output',
        showButton: false
    }
];
const leftInputHandle = [
    {
        id: 'left',
        type: 'target',
        handleType: 'input',
        showButton: false
    }
];
const createCodedAgentNodeWrapper = (translations = DefaultCodedAgentNodeTranslations)=>/*#__PURE__*/ memo(({ data, selected, id, ...nodeProps })=>{
        const nodeData = data;
        const executionStatus = useMemo(()=>{
            if (nodeData.hasError) return 'Failed';
            if (nodeData.hasSuccess) return 'Completed';
            if (nodeData.hasRunning) return 'InProgress';
        }, [
            nodeData.hasError,
            nodeData.hasSuccess,
            nodeData.hasRunning
        ]);
        const statusAdornment = useMemo(()=>{
            if (nodeData.hasError) return /*#__PURE__*/ jsx(CanvasIcon, {
                icon: "circle-alert",
                size: 16,
                color: "var(--canvas-error-icon)"
            });
            if (nodeData.hasSuccess && !nodeData.hasError) return /*#__PURE__*/ jsx(CanvasIcon, {
                icon: "circle-check",
                size: 16,
                color: "var(--canvas-success-icon)"
            });
            if (nodeData.hasRunning && !nodeData.hasError && !nodeData.hasSuccess) return /*#__PURE__*/ jsx(Spinner, {
                size: "sm"
            });
        }, [
            nodeData.hasError,
            nodeData.hasSuccess,
            nodeData.hasRunning
        ]);
        const handleConfigurations = useMemo(()=>[
                {
                    position: Position.Left,
                    handles: leftTargetHandle,
                    visible: true
                },
                {
                    position: Position.Right,
                    handles: rightSourceHandle,
                    visible: true
                }
            ], []);
        const baseNodeConfig = useMemo(()=>({
                executionStatusOverride: executionStatus,
                handleConfigurations,
                adornments: {
                    topRight: statusAdornment
                },
                iconComponent: /*#__PURE__*/ jsx(CodedAgentIcon, {
                    w: 40,
                    h: 40
                })
            }), [
            executionStatus,
            handleConfigurations,
            statusAdornment
        ]);
        return /*#__PURE__*/ jsx(BaseNodeOverrideConfigProvider, {
            value: baseNodeConfig,
            children: /*#__PURE__*/ jsx(BaseNode, {
                ...nodeProps,
                type: "uipath.coded.agent",
                id: id,
                selected: selected,
                data: {
                    ...nodeData,
                    display: {
                        label: nodeData.label,
                        subLabel: translations.codedAgentStep,
                        shape: 'rectangle'
                    }
                }
            })
        });
    });
const CodedResourceNodeElement = /*#__PURE__*/ memo(({ data, selected, id, ...nodeProps })=>{
    const nodeData = data;
    const label = nodeData.label.toLowerCase();
    const executionStatus = useMemo(()=>{
        if (nodeData.hasError) return 'Failed';
        if (nodeData.hasSuccess) return 'Completed';
        if (nodeData.hasRunning) return 'InProgress';
    }, [
        nodeData.hasError,
        nodeData.hasSuccess,
        nodeData.hasRunning
    ]);
    const resourceIcon = useMemo(()=>{
        const resourceType = nodeData.type || '';
        if ('tool' === resourceType || label.includes('tool') || label.includes('function')) return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "wrench",
            size: 40
        });
        if ('context' === resourceType || label.includes('context') || label.includes('knowledge')) return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "network",
            size: 40
        });
        if ('escalation' === resourceType || label.includes('escalation') || label.includes('human')) return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "user",
            size: 40
        });
        return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "message-circle",
            size: 40
        });
    }, [
        label,
        nodeData.type
    ]);
    const statusAdornment = useMemo(()=>{
        if (nodeData.hasError) return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "circle-alert",
            size: 16,
            color: "var(--canvas-error-icon)"
        });
        if (nodeData.hasSuccess && !nodeData.hasError) return /*#__PURE__*/ jsx(CanvasIcon, {
            icon: "circle-check",
            size: 16,
            color: "var(--canvas-success-icon)"
        });
        if (nodeData.hasRunning && !nodeData.hasError && !nodeData.hasSuccess) return /*#__PURE__*/ jsx(Spinner, {
            size: "sm"
        });
    }, [
        nodeData.hasError,
        nodeData.hasSuccess,
        nodeData.hasRunning
    ]);
    const handleConfigurations = useMemo(()=>[
            {
                position: Position.Left,
                handles: leftTargetHandle,
                visible: true
            },
            {
                position: Position.Right,
                handles: rightSourceHandle,
                visible: true
            }
        ], []);
    const baseNodeConfig = useMemo(()=>({
            executionStatusOverride: executionStatus,
            handleConfigurations,
            adornments: {
                topRight: statusAdornment
            },
            iconComponent: resourceIcon
        }), [
        executionStatus,
        handleConfigurations,
        statusAdornment,
        resourceIcon
    ]);
    return /*#__PURE__*/ jsxs("div", {
        style: {
            position: 'relative'
        },
        children: [
            /*#__PURE__*/ jsx(BaseNodeOverrideConfigProvider, {
                value: baseNodeConfig,
                children: /*#__PURE__*/ jsx(BaseNode, {
                    ...nodeProps,
                    type: "uipath.coded.resource",
                    id: id,
                    selected: selected,
                    data: {
                        ...nodeData,
                        display: {
                            label: void 0,
                            shape: 'circle'
                        }
                    }
                })
            }),
            /*#__PURE__*/ jsx(TextContainer, {
                children: /*#__PURE__*/ jsx("span", {
                    className: "text-foreground-muted",
                    children: nodeData.label
                })
            })
        ]
    });
});
const CodedFlowNodeElement = /*#__PURE__*/ memo(({ data, selected, id, ...nodeProps })=>{
    const nodeData = data;
    const isStart = nodeData.label.toLowerCase().includes('start');
    const isEnd = nodeData.label.toLowerCase().includes('end');
    if (isStart || isEnd) {
        const handleConfigs = isStart ? [
            {
                position: Position.Right,
                handles: rightOutputHandle,
                visible: true
            }
        ] : [
            {
                position: Position.Left,
                handles: leftInputHandle,
                visible: true
            }
        ];
        const nodeType = isStart ? 'uipath.coded.flow.start' : 'uipath.coded.flow.end';
        const config = {
            handleConfigurations: handleConfigs
        };
        return /*#__PURE__*/ jsxs("div", {
            style: {
                position: 'relative'
            },
            children: [
                /*#__PURE__*/ jsx(BaseNodeOverrideConfigProvider, {
                    value: config,
                    children: /*#__PURE__*/ jsx(BaseNode, {
                        ...nodeProps,
                        type: nodeType,
                        id: id,
                        selected: selected,
                        data: {
                            ...nodeData,
                            display: {
                                label: void 0,
                                shape: 'square'
                            }
                        }
                    })
                }),
                /*#__PURE__*/ jsx(TextContainer, {
                    children: /*#__PURE__*/ jsx("span", {
                        className: "text-xs text-foreground-muted",
                        children: nodeData.label
                    })
                })
            ]
        });
    }
    const handleConfigs = [
        {
            position: Position.Left,
            handles: leftTargetHandle,
            visible: true
        },
        {
            position: Position.Right,
            handles: rightSourceHandle,
            visible: true
        }
    ];
    const config = {
        handleConfigurations: handleConfigs,
        iconComponent: null
    };
    return /*#__PURE__*/ jsx(BaseNodeOverrideConfigProvider, {
        value: config,
        children: /*#__PURE__*/ jsx(BaseNode, {
            ...nodeProps,
            type: "uipath.coded.flow.node",
            id: id,
            selected: selected,
            data: {
                ...nodeData,
                display: {
                    label: nodeData.label,
                    shape: 'rectangle'
                }
            }
        })
    });
});
const edgeTypes = {
    default: CodedAgentEdge
};
const CodedAgentFlowInner = (props)=>{
    const reactFlowInstance = useReactFlow();
    const [nodes, setNodes, onNodesChange] = useNodesState([]);
    const [edges, setEdges] = useEdgesState([]);
    const [isLoading, setIsLoading] = useState(false);
    const [parseError, setParseError] = useState(null);
    const hasInitialized = useRef(false);
    const edgesRef = useRef([]);
    const agentNodeTranslations = useMemo(()=>props.agentNodeTranslations ?? DefaultCodedAgentNodeTranslations, [
        props.agentNodeTranslations
    ]);
    const nodeTypes = useMemo(()=>({
            agent: createCodedAgentNodeWrapper(agentNodeTranslations),
            resource: CodedResourceNodeElement,
            flow: CodedFlowNodeElement
        }), [
        agentNodeTranslations
    ]);
    const layoutDirection = useMemo(()=>props.layoutDirection || 'LR', [
        props.layoutDirection
    ]);
    useEffect(()=>{
        const processData = async ()=>{
            hasInitialized.current = false;
            if (props.mermaidText && props.mermaidText.length > 0) {
                setIsLoading(true);
                setParseError(null);
                try {
                    const parsedResult = await mermaidToReactFlow(props.mermaidText);
                    if (0 === parsedResult.nodes.length) throw new Error('Invalid mermaid syntax');
                    edgesRef.current = parsedResult.edges;
                    setNodes(parsedResult.nodes);
                    setEdges(parsedResult.edges);
                } catch (error) {
                    setParseError(error.message);
                    setNodes([]);
                    setEdges([]);
                } finally{
                    setIsLoading(false);
                }
            } else {
                setNodes([]);
                setEdges([]);
            }
        };
        processData();
    }, [
        props.mermaidText,
        setEdges,
        setNodes
    ]);
    const autoLayout = useCallback(async ()=>{
        if (hasInitialized.current) return;
        const currentNodes = reactFlowInstance.getNodes();
        if (0 === currentNodes.length) return;
        try {
            const { nodes: layoutNodes } = await d3HierarchyLayout(currentNodes, edgesRef.current, {
                direction: layoutDirection,
                spacing: LAYOUT_SPACING
            });
            setNodes(layoutNodes);
            hasInitialized.current = true;
        } catch  {}
    }, [
        layoutDirection,
        setNodes,
        reactFlowInstance
    ]);
    if (parseError) return /*#__PURE__*/ jsx(CenteredDiv, {
        children: /*#__PURE__*/ jsxs("span", {
            className: "text-error",
            children: [
                "Error: ",
                parseError
            ]
        })
    });
    if (isLoading) return /*#__PURE__*/ jsx(CenteredDiv, {
        children: "Loading..."
    });
    if (0 === nodes.length) return /*#__PURE__*/ jsx(CenteredDiv, {
        children: agentNodeTranslations.noDataToDisplay
    });
    return /*#__PURE__*/ jsx("div", {
        style: {
            width: '100%',
            height: '100%',
            touchAction: 'none'
        },
        children: /*#__PURE__*/ jsxs(BaseCanvas, {
            ref: props.canvasRef,
            nodes: nodes,
            edges: edges,
            nodeTypes: nodeTypes,
            edgeTypes: edgeTypes,
            mode: props.mode || 'view',
            initialAutoLayout: autoLayout,
            onNodesChange: onNodesChange,
            deleteKeyCode: [],
            children: [
                /*#__PURE__*/ jsx(Panel, {
                    position: "top-left",
                    children: /*#__PURE__*/ jsxs(Row, {
                        align: "center",
                        gap: Spacing.SpacingXs,
                        children: [
                            /*#__PURE__*/ jsx(AgentIcon, {
                                w: 20,
                                h: 20
                            }),
                            /*#__PURE__*/ jsx("span", {
                                className: "text-xs font-bold",
                                children: "Coded Agent"
                            })
                        ]
                    })
                }),
                /*#__PURE__*/ jsx(Panel, {
                    position: "bottom-right",
                    children: /*#__PURE__*/ jsx(CanvasPositionControls, {
                        translations: props.canvasTranslations ?? DefaultCanvasTranslations
                    })
                })
            ]
        })
    });
};
const CodedAgentFlow = (props)=>/*#__PURE__*/ jsx(NodeRegistryProvider, {
        manifest: codedAgentManifest,
        children: /*#__PURE__*/ jsx(ReactFlowProvider, {
            children: /*#__PURE__*/ jsx(CodedAgentFlowInner, {
                ...props
            })
        })
    });
export { CodedAgentFlow };
