import { describe, it, expect } from "vitest";
import type { ExecEvent } from "./api";
import { deriveNodes, pendingApproval } from "./run";

let seq = 0;
function ev(node: string, phase: string, extra: Partial<ExecEvent> = {}): ExecEvent {
  return { seq: seq++, ts: 0, node, kind: extra.kind ?? "system", phase, label: extra.label ?? node, ...extra };
}

describe("deriveNodes（ExecEvent 流 → 节点轨迹）", () => {
  it("start → running", () => {
    const [n] = deriveNodes([ev("a", "start")]);
    expect(n.status).toBe("running");
  });

  it("start→end → done 且带耗时", () => {
    const [n] = deriveNodes([ev("a", "start"), ev("a", "end", { ms: 123, detail: "ok" })]);
    expect(n.status).toBe("done");
    expect(n.ms).toBe(123);
    expect(n.detail).toBe("ok");
  });

  it("error → error 状态", () => {
    const [n] = deriveNodes([ev("a", "start"), ev("a", "error", { ms: 5, detail: "boom" })]);
    expect(n.status).toBe("error");
    expect(n.detail).toBe("boom");
  });

  it("已 error 的节点不会被后续 start 覆盖回 running", () => {
    const [n] = deriveNodes([ev("a", "error"), ev("a", "start")]);
    expect(n.status).toBe("error");
  });

  it("info 事件累计到 notes", () => {
    const [n] = deriveNodes([
      ev("a", "info", { detail: "检索到 3 条" }),
      ev("a", "info", { detail: "命中向量库" }),
    ]);
    expect(n.notes).toEqual(["检索到 3 条", "命中向量库"]);
  });

  it("按首次出现顺序聚合多个节点", () => {
    const nodes = deriveNodes([ev("first", "start"), ev("second", "start"), ev("first", "end")]);
    expect(nodes.map((n) => n.node)).toEqual(["first", "second"]);
  });

  it("后续事件可更新 label", () => {
    const [n] = deriveNodes([ev("a", "start", { label: "旧" }), ev("a", "end", { label: "新" })]);
    expect(n.label).toBe("新");
  });

  it("await 事件 → 节点状态 waiting", () => {
    const [n] = deriveNodes([ev("ap", "await", { kind: "approval", label: "审批" })]);
    expect(n.status).toBe("waiting");
  });
});

describe("pendingApproval（HITL 待审批中断）", () => {
  it("await 未收口 → 返回待审批", () => {
    const p = pendingApproval([ev("ap", "await", { kind: "approval", label: "高危审批", detail: "摘要" })]);
    expect(p).toEqual({ node: "ap", title: "高危审批", summary: "摘要" });
  });

  it("await 后 end（同节点）→ 已决，返回 null", () => {
    const p = pendingApproval([
      ev("ap", "await", { kind: "approval" }),
      ev("ap", "end", { kind: "approval" }),
    ]);
    expect(p).toBeNull();
  });

  it("await 后 error（超时/拒绝）→ 已决，返回 null", () => {
    const p = pendingApproval([
      ev("ap", "await", { kind: "approval" }),
      ev("ap", "error", { kind: "approval" }),
    ]);
    expect(p).toBeNull();
  });

  it("无审批事件 → null", () => {
    expect(pendingApproval([ev("a", "start"), ev("a", "end")])).toBeNull();
  });
});
