/**
 * 意圖語法寫得出條件分支 → 編圖帶對邊型與標籤（SDD workflow-discovery 3.11）
 *
 * 為什麼補這一支（08-01 施工中自查發現的斷點，差點漏掉）：
 *   引擎支援了 ON_TRUE/ON_FALSE/ON_BRANCH，skill 文件也教了寫法，
 *   但 `graph-builder` 原本**只認得 `對每個 X` 的參數化 label**，
 *   `ON_BRANCH(branch_active)` 這種帶括號的 label 會落到 `toEdgeType` 的預設值 **PIPE**
 *   ⇒ 「教了語法但引擎不收，而且是靜默的」——比沒做更糟（AI 以為分支了，實際全走同一條）。
 *
 * 本檔守的就是「文件教的寫法，編圖真的收得到」這條線。
 */
import { describe, it, expect } from 'vitest';
import { buildExecutionGraph } from '../src/actions/graph-builder';
import { parseTriplets, resolveNodeRole } from '../src/actions/triplet-parser';

/** 把意圖字串編成圖（走 AI 真正會走的那條路：triplets → graph）。
 *  nodeResults 用「全部 found」的最小替身——本檔只驗**邊**的編法，零件解析另有測試。 */
function build(triplets: string[]) {
  const parsed = parseTriplets(triplets)!;
  const nodeResults: Record<string, { status: 'found'; componentId: string; type: ReturnType<typeof resolveNodeRole> }> = {};
  for (const name of parsed.nodeNames) {
    nodeResults[name] = {
      status: 'found',
      componentId: name.toLowerCase().replace(/\s+/g, '_'),
      type: resolveNodeRole(name, parsed),
    };
  }
  return buildExecutionGraph(parsed, nodeResults as never, 'test-graph', '測試');
}

function edgeBetween(graph: ReturnType<typeof build>, from: string, to: string) {
  return graph.edges.find(e => e.from === from && e.to === to);
}

describe('意圖語法：if_control 兩路（ON_TRUE／ON_FALSE）', () => {
  it('ON_TRUE／ON_FALSE 編成對應邊型，不會退化成 PIPE', () => {
    const g = build([
      'input >> ON_SUCCESS >> 判斷有沒有新資料',
      '判斷有沒有新資料 >> ON_TRUE >> 傳到telegram',
      '判斷有沒有新資料 >> ON_FALSE >> 結束',
    ]);
    expect(edgeBetween(g, '判斷有沒有新資料', '傳到telegram')?.type).toBe('ON_TRUE');
    expect(edgeBetween(g, '判斷有沒有新資料', '結束')?.type).toBe('ON_FALSE');
  });

  it('中文語意詞「成立時」「否則」也編得出來', () => {
    const g = build([
      '判斷有沒有新資料 >> 成立時 >> 傳到telegram',
      '判斷有沒有新資料 >> 否則 >> 結束',
    ]);
    expect(edgeBetween(g, '判斷有沒有新資料', '傳到telegram')?.type).toBe('ON_TRUE');
    expect(edgeBetween(g, '判斷有沒有新資料', '結束')?.type).toBe('ON_FALSE');
  });
});

describe('意圖語法：switch 具名分支（ON_BRANCH(標籤)）', () => {
  it('括號裡的標籤被抽成 edge.branch，型別是 ON_BRANCH', () => {
    const g = build([
      'my_switch >> ON_BRANCH(branch_active) >> 處理啟用',
      'my_switch >> ON_BRANCH(branch_pending) >> 處理待辦',
      'my_switch >> ON_BRANCH(branch_default) >> 其他',
    ]);
    const active = edgeBetween(g, 'my_switch', '處理啟用');
    expect(active?.type).toBe('ON_BRANCH');
    expect(active?.branch).toBe('branch_active');

    const pending = edgeBetween(g, 'my_switch', '處理待辦');
    expect(pending?.branch).toBe('branch_pending');

    const dflt = edgeBetween(g, 'my_switch', '其他');
    expect(dflt?.branch).toBe('branch_default');
  });

  it('全形括號也收（中文輸入法常打出全形）', () => {
    const g = build(['my_switch >> ON_BRANCH（branch_active） >> 處理啟用']);
    const e = edgeBetween(g, 'my_switch', '處理啟用');
    expect(e?.type).toBe('ON_BRANCH');
    expect(e?.branch).toBe('branch_active');
  });

  it('try_catch 的 try／catch 標籤同樣收得到', () => {
    const g = build([
      'my_try >> ON_BRANCH(try) >> 正常流程',
      'my_try >> ON_BRANCH(catch) >> 補救流程',
    ]);
    expect(edgeBetween(g, 'my_try', '正常流程')?.branch).toBe('try');
    expect(edgeBetween(g, 'my_try', '補救流程')?.branch).toBe('catch');
  });
});

describe('零變化：既有語法不受影響', () => {
  it('ON_SUCCESS 仍是 ON_SUCCESS', () => {
    const g = build(['input >> ON_SUCCESS >> prep']);
    expect(edgeBetween(g, 'input', 'prep')?.type).toBe('ON_SUCCESS');
  });

  it('「對每個 X」仍抽得到 iterator（不被新的 branch 抽取干擾）', () => {
    const g = build(['parse_card >> 對每個 block >> post_block']);
    const e = edgeBetween(g, 'parse_card', 'post_block');
    expect(e?.type).toBe('FOREACH');
    expect(e?.iterator).toBe('block');
    expect(e?.branch).toBeUndefined();
  });
});
