import fs from "fs";
import os from "os";
import path from "path";
import { afterEach, describe, expect, it } from "vitest";
import { createRunLogRegistry } from "./logs.mjs";
import { createSetupOperationRegistry } from "./setup-operations.mjs";

const tempDirs = [];

afterEach(() => {
  while (tempDirs.length > 0) {
    fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
  }
});

function makeTempDir(prefix) {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
  tempDirs.push(dir);
  return dir;
}

function makeConfig(productDir) {
  return {
    name: "api",
    runtimeLabel: "api",
    productDir,
  };
}

describe("setup operation registry", () => {
  it("tracks running and finished setup operations with log refs", () => {
    const productDir = makeTempDir("testkit-setup-ops-");
    const logRegistry = createRunLogRegistry(productDir);
    const changes = [];
    const registry = createSetupOperationRegistry({
      logRegistry,
      onChange(operations) {
        changes.push(operations);
      },
    });

    const operation = registry.start({
      config: makeConfig(productDir),
      stage: "template:migrate:api:1",
      kind: "setup-step",
      summary: "command: node scripts/migrate.mjs",
    });

    expect(operation.logRef).toMatchObject({
      path: ".testkit/results/setup/api__api__template-migrate-api-1.log",
      stage: "template:migrate:api:1",
    });

    const finished = registry.finish(operation, {
      status: "passed",
      summary: "command: node scripts/migrate.mjs",
    });

    expect(finished.status).toBe("passed");
    expect(finished.durationMs).toBeGreaterThanOrEqual(0);
    expect(registry.listOperations()).toEqual([
      expect.objectContaining({
        stage: "template:migrate:api:1",
        kind: "setup-step",
        status: "passed",
        summary: "command: node scripts/migrate.mjs",
        logRef: operation.logRef,
      }),
    ]);
    expect(changes).toHaveLength(2);

    logRegistry.closeAll();
  });

  it("records cached setup operations without logs", () => {
    const productDir = makeTempDir("testkit-setup-ops-cached-");
    const registry = createSetupOperationRegistry();

    const operation = registry.recordCached({
      config: makeConfig(productDir),
      stage: "template",
      kind: "database-template",
      summary: "template cache hit",
    });

    expect(operation).toMatchObject({
      stage: "template",
      kind: "database-template",
      status: "cached",
      summary: "template cache hit",
      logRef: null,
    });
  });
});
