import type { WorkflowConfig, WorkflowDefinition } from '../../api/workflows' import type { WorkflowGraphFamily, WorkflowNodeDefinitionMap } from './workflowNodeLibrary' import { getNodeFamily } from './workflowNodeLibrary' export const BLUEPRINT_LABELS: Record = { cad_intake: 'Reference Blueprint', order_rendering: 'Reference Blueprint', still_graph_reference: 'Graph Reference', starter_cad_intake: 'Starter', starter_order_rendering: 'Starter', } export const BLUEPRINT_DESCRIPTION: Record = { cad_intake: 'Canonical CAD-file workflow for intake, preview generation, and material discovery.', order_rendering: 'Canonical order-line workflow for production rendering, exports, and notifications.', still_graph_reference: 'Reference still-render graph that stays parallel to the legacy workflow while native nodes reach parity.', starter_cad_intake: 'Minimal CAD-file starter graph.', starter_order_rendering: 'Minimal order-line starter graph.', } export function inferWorkflowFamily( config: WorkflowConfig, nodeDefinitionsByStep?: WorkflowNodeDefinitionMap, ): WorkflowGraphFamily { const nodes = Array.isArray(config.nodes) ? config.nodes : [] if (nodes.length > 0) { const families = new Set(nodes.map(node => getNodeFamily(node.step, nodeDefinitionsByStep))) if (families.size === 1) { return Array.from(families)[0] } return 'mixed' } const presetType = config.ui?.preset ?? 'custom' if (presetType === 'custom') { return 'mixed' } return 'order_line' } export function getWorkflowBlueprint(config: WorkflowConfig): string | null { const blueprint = config.ui?.blueprint return typeof blueprint === 'string' && blueprint.trim().length > 0 ? blueprint : null } export function isReferenceBlueprint(config: WorkflowConfig): boolean { const blueprint = getWorkflowBlueprint(config) return blueprint === 'cad_intake' || blueprint === 'order_rendering' || blueprint === 'still_graph_reference' } export function cloneWorkflowConfig(config: WorkflowConfig, options?: { stripBlueprint?: boolean }): WorkflowConfig { const nextUi = { ...(config.ui ?? {}) } if (options?.stripBlueprint) { delete nextUi.blueprint } return { version: config.version, nodes: config.nodes.map(node => ({ ...node, params: { ...(node.params ?? {}) }, ui: node.ui ? { ...node.ui } : undefined, })), edges: config.edges.map(edge => ({ ...edge })), ui: nextUi, } } export function compareWorkflows(a: WorkflowDefinition, b: WorkflowDefinition): number { const blueprintRank = Number(isReferenceBlueprint(b.config)) - Number(isReferenceBlueprint(a.config)) if (blueprintRank !== 0) return blueprintRank const activeRank = Number(b.is_active) - Number(a.is_active) if (activeRank !== 0) return activeRank return a.name.localeCompare(b.name) }