import { describe, expect, test } from "bun:test";
import { createWorkflowEngine, defineDurableWorkflow, memoryWorkflowStore } from "../src/index.ts";

describe("durable workflows", () => {
  test("runs dependency steps and persists results", async () => {
    const store = memoryWorkflowStore();
    const engine = createWorkflowEngine(store);
    const workflow = defineDurableWorkflow({
      name: "report",
      steps: [
        { name: "load", run: (input: number) => input * 2 },
        { name: "render", dependsOn: ["load"], run: (input: number) => `report:${input}` },
      ],
    });
    const result = await engine.start(workflow, 4, "report-1");
    expect(result.status).toBe("completed");
    expect(result.results.render).toBe("report:8");
    expect((await store.get("report-1"))?.progress).toBe(100);
  });
  test("pauses for a durable human approval and resumes", async () => {
    const engine = createWorkflowEngine();
    const workflow = defineDurableWorkflow({
      name: "publish",
      steps: [
        { name: "draft", run: () => "ready" },
        { name: "approve", dependsOn: ["draft"], approval: true, run: (input: string) => input },
        { name: "publish", dependsOn: ["approve"], run: () => "published" },
      ],
    });
    const waiting = await engine.start(workflow, null, "publish-1");
    expect(waiting).toMatchObject({ status: "waiting-approval", waitingFor: "approve" });
    const completed = await engine.approve(workflow, "publish-1", "approve", "user-42");
    expect(completed.status).toBe("completed");
    expect(completed.results["approve:approval"]).toMatchObject({ actor: "user-42" });
  });
  test("rejects invalid dependency graphs", () => {
    expect(() =>
      defineDurableWorkflow({
        name: "bad",
        steps: [{ name: "a", dependsOn: ["missing"], run() {} }],
      }),
    ).toThrow("WRN-WORKFLOW-DEPENDENCY");
    expect(() =>
      defineDurableWorkflow({
        name: "cycle",
        steps: [
          { name: "a", dependsOn: ["b"], run() {} },
          { name: "b", dependsOn: ["a"], run() {} },
        ],
      }),
    ).toThrow("WRN-WORKFLOW-CYCLE");
  });
});
