import { describe, it, expect } from "vitest";
import type { Node, Edge } from "@xyflow/react";
import { exportDsl, validate } from "./dsl";

// 构造画布节点的小工具（只填导出/校验关心的字段）。
function node(id: string, kind: string, config?: unknown, label?: string): Node {
  return { id, position: { x: 0, y: 0 }, data: { kind, label, config } } as unknown as Node;
}
function edge(source: string, target: string, sourceHandle?: string): Edge {
  return { id: `${source}-${target}`, source, target, sourceHandle } as unknown as Edge;
}

describe("exportDsl", () => {
  it("把节点映射为 {id,kind,label,config}", () => {
    const dsl = exportDsl([node("in", "input", { text: "hi" }, "输入")], []);
    expect(dsl.version).toBe("1");
    expect(dsl.nodes).toEqual([{ id: "in", kind: "input", label: "输入", config: { text: "hi" } }]);
  });

  it("缺失 config 时回退为空对象", () => {
    const dsl = exportDsl([node("in", "input")], []);
    expect(dsl.nodes[0].config).toEqual({});
  });

  it("仅在存在 sourceHandle 时才带上该字段（branch 真/假边）", () => {
    const dsl = exportDsl(
      [node("b", "branch"), node("t", "agent"), node("f", "agent")],
      [edge("b", "t", "true"), edge("b", "f")],
    );
    expect(dsl.edges[0]).toEqual({ source: "b", target: "t", sourceHandle: "true" });
    expect(dsl.edges[1]).toEqual({ source: "b", target: "f" });
    expect("sourceHandle" in dsl.edges[1]).toBe(false);
  });
});

describe("validate", () => {
  it("空画布报 error", () => {
    const issues = validate([], []);
    expect(issues).toHaveLength(1);
    expect(issues[0].level).toBe("error");
  });

  it("单节点不报孤立警告（length>1 才校验连线）", () => {
    const issues = validate([node("in", "input", { text: "hi" })], []);
    expect(issues.some((i) => i.msg.includes("孤立"))).toBe(false);
  });

  it("多节点中未连线的节点报孤立 warn", () => {
    const issues = validate(
      [node("a", "input", { text: "hi" }), node("b", "agent", { system: "x" })],
      [], // 都没连
    );
    expect(issues.filter((i) => i.msg.includes("孤立"))).toHaveLength(2);
  });

  it("必填项缺失报 warn（input.text 为必填）", () => {
    const issues = validate([node("in", "input", { text: "" })], []);
    expect(issues.some((i) => i.level === "warn" && i.msg.includes("缺必填项"))).toBe(true);
  });
});
