import { describe, expect, test } from "vitest";
import { nextHealth, type PreviousHealth } from "@/server/health/transition";

const day = (n: number) => new Date(`2026-09-${String(n).padStart(2, "0")}T03:30:00Z`);
const healthy: PreviousHealth = { failureStartedAt: null, lastRecoveredAt: null };

describe("Not Working Since (spec §15–16)", () => {
  test("Working → Not Working records when the failure started", () => {
    expect(nextHealth(healthy, "NOT_WORKING", day(15))).toEqual({
      failureStartedAt: day(15),
      lastRecoveredAt: null,
      event: "failure_started",
    });
  });

  test("later failures never overwrite the original failure start", () => {
    let state: PreviousHealth = healthy;
    for (const n of [15, 16, 17]) state = nextHealth(state, "NOT_WORKING", day(n));
    expect(state.failureStartedAt).toEqual(day(15));
    expect(nextHealth(state, "NOT_WORKING", day(18)).event).toBeNull();
  });

  test("recovery clears the failure start and records last_recovered_at", () => {
    const failing: PreviousHealth = { failureStartedAt: day(15), lastRecoveredAt: null };
    expect(nextHealth(failing, "WORKING", day(18))).toEqual({
      failureStartedAt: null,
      lastRecoveredAt: day(18),
      event: "recovered",
    });
  });

  test("a healthy check on a healthy app changes nothing", () => {
    const previous: PreviousHealth = { failureStartedAt: null, lastRecoveredAt: day(10) };
    expect(nextHealth(previous, "WORKING", day(18))).toEqual({
      failureStartedAt: null,
      lastRecoveredAt: day(10),
      event: null,
    });
  });

  test("the very first check failing also starts an outage", () => {
    expect(nextHealth(healthy, "NOT_WORKING", day(1)).failureStartedAt).toEqual(day(1));
  });

  test("a Slow response counts as up: it ends an outage and never starts one", () => {
    const failing: PreviousHealth = { failureStartedAt: day(15), lastRecoveredAt: null };
    expect(nextHealth(failing, "SLOW", day(18))).toEqual({ failureStartedAt: null, lastRecoveredAt: day(18), event: "recovered" });
    expect(nextHealth(healthy, "SLOW", day(18))).toEqual({ failureStartedAt: null, lastRecoveredAt: null, event: null });
  });

  test("a second outage gets its own start while keeping the previous recovery time", () => {
    const recovered = nextHealth({ failureStartedAt: day(15), lastRecoveredAt: null }, "WORKING", day(18));
    const again = nextHealth(recovered, "NOT_WORKING", day(20));
    expect(again.failureStartedAt).toEqual(day(20));
    expect(again.lastRecoveredAt).toEqual(day(18));
  });
});
