import type { ParsedTriplets } from './triplet-parser';
import { toEdgeType } from './triplet-parser';
import type { SearchResult } from './search-nodes';

/** 從 nodeResults + parsed 組成可直接送入 /execute 的 ExecutionGraph
 *
 * config 格式（來自 workflow YAML 的 config 欄位）：
 *   { node_name: { component: "cmp_xxxxxxxx" | "rec_xxxxxxxx" | canonical_id, ...params } }
 *
 * 若 config[node].component 存在，以它覆蓋 searchNodes 偵測到的 componentId。
 * config[node] 的其他欄位作為節點靜態參數（node.data），合併進執行 context。
 */
export function buildExecutionGraph(
  parsed: ParsedTriplets,
  nodeResults: SearchResult['nodeResults'],
  graphId: string,
  graphName: string,
  config?: Record<string, Record<string, unknown>>,
) {
  const nodes = [...parsed.nodeNames].map(name => {
    const nr = nodeResults[name]!;
    const id = name.toLowerCase().replace(/\s+/g, '-');
    const nodeConfig = config?.[name] ?? {};

    // config[name].component 可以是 hash 或 canonical_id，覆蓋自動偵測的 componentId
    const componentId = (nodeConfig.component as string | undefined) ?? nr.componentId;

    // 其他 config 欄位作為 node.data（靜態參數）
    const { component: _component, ...staticParams } = nodeConfig;
    const data = Object.keys(staticParams).length > 0 ? staticParams : undefined;

    return { id, type: nr.type, componentId, label: name, data };
  });

  const edges = parsed.edges.map(e => {
    // 「對每個 X」label 抽 iterator：cypher binding 表達 FOREACH 的迭代變數
    // 例：'A >> 對每個 paragraph >> B' → type=FOREACH, iterator='paragraph'
    //     getIterableFromContext 會找 ctx.paragraphs（複數）或 ctx.paragraph
    let iterator: string | undefined;
    let label = e.label;
    const foreachMatch = label.match(/^(?:對每個|FOREACH)\s+(\w+)$/i);
    if (foreachMatch) {
      iterator = foreachMatch[1];
      label = '對每個';  // 改回標準 label 走 SEMANTIC_EDGE_MAP
    }

    // 「ON_BRANCH(標籤)」抽 branch：意圖語法表達具名分支（SDD workflow-discovery 3.11）
    // 例：'my_switch >> ON_BRANCH(branch_active) >> 處理啟用' → type=ON_BRANCH, branch='branch_active'
    // 沒有這段的話，帶括號的 label 會落到 toEdgeType 的預設值 PIPE ⇒ 分支靜默失效
    // （即「教了語法但引擎不收」——比沒做更糟，故與 skill 文件同批補上）
    let branch: string | undefined;
    const branchMatch = label.match(/^(?:ON_BRANCH|分支)\s*[（(]\s*([\w-]+)\s*[）)]$/i);
    if (branchMatch) {
      branch = branchMatch[1];
      label = 'ON_BRANCH';
    }

    const edge: {
      from: string; to: string; type: ReturnType<typeof toEdgeType>;
      iterator?: string; branch?: string;
    } = {
      from: e.from.toLowerCase().replace(/\s+/g, '-'),
      to: e.to.toLowerCase().replace(/\s+/g, '-'),
      type: toEdgeType(label),
    };
    if (iterator) edge.iterator = iterator;
    if (branch) edge.branch = branch;
    return edge;
  });

  return { id: graphId, name: graphName, nodes, edges };
}
