import { afterEach, describe, expect, test } from "bun:test";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { collectSeats } from "./seats";
import type { LedgerReadResult } from "../sessions/ledger";

const roots: string[] = [];
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
function fixture(): string { const root = mkdtempSync(join(tmpdir(), "overdeck-seats-")); roots.push(root); return root; }
const emptyLedger = async (): Promise<LedgerReadResult> => ({ sessions: [], dir: "fixture", missing: false, unreadable: [] });

describe("seats adapter", () => {
  test("marks a stale stamp free when its flock probe succeeds", async () => {
    const dir = fixture(); writeFileSync(join(dir, "slot-0.lock"), "999999\t1\tstale\n");
    const snapshot = await collectSeats({ dir, cap: 1, probe: () => true, readLedgerImpl: emptyLedger });
    expect(snapshot.rows[0]).toMatchObject({ state: "free", holder: null });
  });
  test("uses lock holders, not the stamp pid, to resolve a held ledger session", async () => {
    const dir = fixture(); writeFileSync(join(dir, "slot-0.lock"), "999999\t1\tstamp\n");
    const pid = process.pid;
    const ledger = async (): Promise<LedgerReadResult> => ({ sessions: [{ id: "ledger", pid, title: "Current session", runId: "run-1" }] as LedgerReadResult["sessions"], dir, missing: false, unreadable: [] });
    const snapshot = await collectSeats({ dir, cap: 1, probe: () => false, holders: () => [pid], readLedgerImpl: ledger });
    expect(snapshot.rows[0]?.holder).toMatchObject({ pid, sessionId: "ledger", sessionName: "Current session", adwId: "run-1" });
  });
  test("marks a contended lock held only when its stamp still matches proc", async () => {
    const dir = fixture(); const ticks = (await Bun.file(`/proc/${process.pid}/stat`).text()).split(' ')[21]!;
    writeFileSync(join(dir, "slot-0.lock"), `${process.pid}\t${ticks}\tcurrent\n`);
    const snapshot = await collectSeats({ dir, cap: 1, probe: () => false, holders: () => [process.pid], readLedgerImpl: emptyLedger });
    expect(snapshot.rows[0]?.state).toBe("held");
  });
  test("labels a confirmed dead stamp with no lock holder wedged", async () => {
    const dir = fixture(); writeFileSync(join(dir, "slot-0.lock"), "999999\t1\tdead\n");
    const snapshot = await collectSeats({ dir, cap: 1, probe: () => false, holders: () => [], readLedgerImpl: emptyLedger });
    expect(snapshot.rows[0]?.state).toBe("wedged");
  });
  test("does not guess when confirmation is unavailable", async () => {
    const dir = fixture(); writeFileSync(join(dir, "slot-0.lock"), "999999\t1\tdead\n");
    const snapshot = await collectSeats({ dir, cap: 1, probe: () => false, holders: () => null, readLedgerImpl: emptyLedger });
    expect(snapshot.rows[0]?.state).toBe("unknown");
  });
  test("fails unavailable directories instead of inventing a pool", async () => {
    await expect(collectSeats({ dir: join(fixture(), "missing"), readLedgerImpl: emptyLedger })).rejects.toThrow("limiter state unavailable");
  });
});
