import { describe, expect, it } from "vitest";
import { nextPollStep, POLL_MAX_FAILURES } from "./poll";

const isFinal = (status: string) => status === "done" || status === "failed";

describe("nextPollStep", () => {
  it("continue tant que le job n'est pas terminé", () => {
    expect(nextPollStep({ status: "value", value: "running" }, isFinal, 0)).toEqual({
      action: "continue",
    });
  });

  it("s'arrête sur un état terminal", () => {
    expect(nextPollStep({ status: "value", value: "done" }, isFinal, 0)).toEqual({
      action: "stop",
    });
    expect(nextPollStep({ status: "value", value: "failed" }, isFinal, 0)).toEqual({
      action: "stop",
    });
  });

  it("abandonne immédiatement sur un refus de l'api", () => {
    expect(nextPollStep({ status: "refused", error: "Job inconnu" }, isFinal, 0)).toEqual({
      action: "fail",
      error: "Job inconnu",
    });
  });

  it("retente tant que le plafond d'échecs de transport n'est pas atteint", () => {
    for (let failures = 1; failures < POLL_MAX_FAILURES; failures += 1) {
      expect(nextPollStep({ status: "unreachable", error: "réseau" }, isFinal, failures)).toEqual({
        action: "continue",
      });
    }
  });

  it("abandonne au plafond d'échecs de transport consécutifs", () => {
    expect(
      nextPollStep({ status: "unreachable", error: "réseau" }, isFinal, POLL_MAX_FAILURES),
    ).toEqual({ action: "fail", error: "réseau" });
  });

  it("un refus n'est jamais retenté, même au premier échec", () => {
    expect(nextPollStep({ status: "refused", error: "404" }, isFinal, 1).action).toBe("fail");
  });

  it("respecte un plafond explicite", () => {
    expect(nextPollStep({ status: "unreachable", error: "x" }, isFinal, 1, 1).action).toBe("fail");
    expect(nextPollStep({ status: "unreachable", error: "x" }, isFinal, 1, 9).action).toBe(
      "continue",
    );
  });
});
