import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { buildControllerStatus } from "./status";
import { ControllerStore } from "./store";

describe("reported job status", () => {
  let dir: string;
  let store: ControllerStore;

  beforeEach(() => {
    dir = mkdtempSync(join(tmpdir(), "controller-status-"));
    store = new ControllerStore(join(dir, "state.sqlite"));
  });

  afterEach(() => {
    store.close();
    rmSync(dir, { recursive: true, force: true });
  });

  test("projects stale running jobs at read time without writing", () => {
    store.upsertJob({
      id: "stale-job", repo: "owner/repo", host: "debian1", snapshot: "1",
      stage: "running", attempt: 1, rc: null, infraFailure: false,
      startedAt: "2026-07-20T00:00:00.000Z",
      lastReportAt: "2026-07-20T00:00:05.000Z", timeoutSec: 10,
    });
    const revision = store.getRevision();
    const status = buildControllerStatus(
      store,
      undefined,
      () => Date.parse("2026-07-20T00:00:15.000Z"),
    );
    expect(status.jobs[0]?.stage).toBe("stale");
    expect(store.getJob("stale-job")?.stage).toBe("running");
    expect(store.getRevision()).toBe(revision);
    expect(store.readEvents()).toEqual([]);
  });

  test("derives observed 24h route, success, and exit-127 samples from the job ledger", () => {
    const now = Date.parse("2026-07-20T12:00:00.000Z");
    const jobs = [
      { id: "ok", host: "debian1", startedAt: "2026-07-20T10:00:00.000Z", finishedAt: "2026-07-20T10:10:00.000Z", rc: 0 },
      { id: "missing", host: "debian2", startedAt: "2026-07-20T09:00:00.000Z", finishedAt: "2026-07-20T09:10:00.000Z", rc: 127 },
      { id: "running", host: "debian1", startedAt: "2026-07-20T08:00:00.000Z", rc: null },
      { id: "old", host: "debian1", startedAt: "2026-07-19T11:59:59.000Z", finishedAt: "2026-07-19T12:10:00.000Z", rc: 0 },
    ];
    for (const job of jobs) {
      store.upsertJob({
        id: job.id, repo: "owner/repo", host: job.host, snapshot: job.id,
        stage: job.rc === null ? "running" : job.rc === 0 ? "succeeded" : "failed",
        attempt: 1, rc: job.rc, infraFailure: false, startedAt: job.startedAt,
        ...("finishedAt" in job ? { finishedAt: job.finishedAt } : {}),
      });
    }

    expect(buildControllerStatus(store, undefined, () => now).kpis).toEqual({
      remote24h: 3,
      remoteSuccessPct: 50,
      exit127: { count: 1, hosts: ["debian2"] },
    });
  });

  test("leaves success unrecorded when no 24h job has a terminal result", () => {
    store.upsertJob({
      id: "running", repo: "owner/repo", host: "debian1", snapshot: "1",
      stage: "running", attempt: 1, rc: null, infraFailure: false,
      startedAt: "2026-07-20T10:00:00.000Z",
    });
    expect(buildControllerStatus(
      store,
      undefined,
      () => Date.parse("2026-07-20T12:00:00.000Z"),
    ).kpis).toEqual({ remote24h: 1, exit127: { count: 0, hosts: [] } });
  });
});
