import type { Edge, Node } from '@xyflow/react' import type { AutomationWorkflow, WorkflowEdgeDef, WorkflowNodeData, WorkflowNodeDef, WorkflowNodeType, } from './types' import { nextNodeId } from './defaults' import type { ActionsNodeData, ConditionNodeData, LabelCheckNodeData, LLMCheckNodeData, SetVarNodeData, SwitchNodeData } from './types' export function workflowNodesToFlow(nodes: WorkflowNodeDef[]): Node[] { return nodes.map((n) => ({ id: n.id, type: n.type, position: n.position, data: n.data as Record, })) } export function workflowEdgesToFlow(edges: WorkflowEdgeDef[]): Edge[] { return edges.map((e) => ({ id: e.id, source: e.source, target: e.target, sourceHandle: e.sourceHandle ?? null, animated: true, })) } export function flowToWorkflow( kind: AutomationWorkflow['kind'], triggers: AutomationWorkflow['triggers'], variables: AutomationWorkflow['variables'], nodes: Node[], edges: Edge[] ): AutomationWorkflow { return { version: 1, kind, triggers, variables, nodes: nodes.map((n) => ({ id: n.id, type: n.type as WorkflowNodeType, position: n.position, data: (n.data ?? {}) as WorkflowNodeData, })), edges: edges.map((e) => ({ id: e.id, source: e.source, target: e.target, sourceHandle: e.sourceHandle ?? undefined, })), } } export function defaultDataForNodeType(type: WorkflowNodeType): WorkflowNodeData { switch (type) { case 'condition': return { field: 'subject', operator: 'contains', value: '' } satisfies ConditionNodeData case 'label_check': return { label: '', operator: 'has' } satisfies LabelCheckNodeData case 'switch': return { field: 'subject', cases: [ { value: 'facture', label: 'Factures' }, { value: 'newsletter', label: 'Newsletters' }, ], } satisfies SwitchNodeData case 'llm_check': return { prompt: 'Ce message est-il du spam ou une arnaque ?', provider: '', model: '', } satisfies LLMCheckNodeData case 'actions': return { actions: [{ type: 'label', value: '' }] } satisfies ActionsNodeData case 'set_var': return { name: 'result', value: '{{subject}}' } satisfies SetVarNodeData case 'call_function': case 'call_rule': return { rule_id: '' } default: return {} } } export function createFlowNode( type: WorkflowNodeType, position: { x: number; y: number } ): Node { return { id: nextNodeId(type), type, position, data: defaultDataForNodeType(type) as Record, } } export function parseWorkflowFromRule( workflow: unknown, ruleKind: 'rule' | 'function' ): AutomationWorkflow | null { if (!workflow || typeof workflow !== 'object') return null const w = workflow as AutomationWorkflow if (!Array.isArray(w.nodes) || w.nodes.length === 0) return null return { version: 1, kind: w.kind ?? ruleKind, triggers: w.triggers ?? { operator: 'or', groups: [{ operator: 'and', items: [{ type: 'message_received' }] }], }, variables: w.variables ?? [], nodes: w.nodes, edges: w.edges ?? [], } }