import fs from "fs";
import os from "os";
import path from "path";
import { afterEach, describe, expect, it } from "vitest";
import {
  getLocalInfraDir,
  getLocalLocksDir,
  getLocalServiceCacheDir,
  hasRemainingLocalArtifacts,
  readStateValue,
  visitDirs,
} from "./state.mjs";

const tempDirs = [];

afterEach(() => {
  for (const dir of tempDirs.splice(0)) {
    fs.rmSync(dir, { recursive: true, force: true });
  }
});

function mkTempDir() {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-db-state-"));
  tempDirs.push(dir);
  return dir;
}

describe("database-state", () => {
  it("builds local state paths", () => {
    expect(getLocalInfraDir("/tmp/product")).toBe("/tmp/product/.testkit/_infra/local-postgres");
    expect(getLocalLocksDir("/tmp/product")).toBe("/tmp/product/.testkit/_infra/local-postgres/locks");
    expect(getLocalServiceCacheDir("/tmp/product", "api")).toBe("/tmp/product/.testkit/_dbcache/api");
  });

  it("reads state values and visits directories", () => {
    const productDir = mkTempDir();
    const aDir = path.join(productDir, "a");
    const bDir = path.join(aDir, "b");
    fs.mkdirSync(bDir, { recursive: true });
    fs.writeFileSync(path.join(aDir, "value"), " hello \n");

    const visited = [];
    visitDirs(productDir, (dir) => visited.push(path.relative(productDir, dir)));

    expect(visited).toEqual(["a", path.join("a", "b")]);
    expect(readStateValue(path.join(aDir, "value"))).toBe("hello");
    expect(readStateValue(path.join(aDir, "missing"))).toBeNull();
  });

  it("detects remaining local artifacts", () => {
    const productDir = mkTempDir();
    const runtimeDir = path.join(productDir, ".testkit", "api");
    fs.mkdirSync(runtimeDir, { recursive: true });
    fs.writeFileSync(path.join(runtimeDir, "database_backend"), "local");

    expect(hasRemainingLocalArtifacts(productDir, readStateValue)).toBe(true);

    fs.rmSync(path.join(productDir, ".testkit"), { recursive: true, force: true });
    fs.mkdirSync(path.join(productDir, ".testkit", "_dbcache", "api"), { recursive: true });

    expect(hasRemainingLocalArtifacts(productDir, readStateValue)).toBe(true);

    fs.rmSync(path.join(productDir, ".testkit"), { recursive: true, force: true });
    expect(hasRemainingLocalArtifacts(productDir, readStateValue)).toBe(false);
  });
});
