import { afterEach, describe, it } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { loadWorkspaceEnv, resolveWorkspaceEnvPaths } from "./load-workspace-env.js";

const envKeys = [
  "DATABASE_URL",
  "SHARED_VALUE",
  "LOCAL_ONLY",
  "MODE_ONLY",
  "MODE_LOCAL_ONLY",
];

function clearEnv() {
  for (const key of envKeys) {
    delete process.env[key];
  }
}

function withTempWorkspace(run: (workspaceRoot: string) => void) {
  const workspaceRoot = mkdtempSync(join(tmpdir(), "capakraken-env-"));

  try {
    run(workspaceRoot);
  } finally {
    rmSync(workspaceRoot, { recursive: true, force: true });
  }
}

afterEach(() => {
  clearEnv();
  delete process.env.NODE_ENV;
});

describe("loadWorkspaceEnv", () => {
  it("loads standard workspace env files in precedence order", () => {
    withTempWorkspace((workspaceRoot) => {
      writeFileSync(join(workspaceRoot, ".env"), "DATABASE_URL=postgres://from-env\nSHARED_VALUE=base\n");
      writeFileSync(join(workspaceRoot, ".env.development"), "SHARED_VALUE=mode\nMODE_ONLY=development\n");
      writeFileSync(join(workspaceRoot, ".env.local"), "SHARED_VALUE=local\nLOCAL_ONLY=1\n");
      writeFileSync(join(workspaceRoot, ".env.development.local"), "SHARED_VALUE=mode-local\nMODE_LOCAL_ONLY=1\n");
      process.env.NODE_ENV = "development";

      const loadedPaths = loadWorkspaceEnv({ workspaceRoot });

      assert.deepEqual(
        loadedPaths.map((entry) => entry.slice(workspaceRoot.length + 1)),
        [".env", ".env.development", ".env.local", ".env.development.local"],
      );
      assert.equal(process.env.DATABASE_URL, "postgres://from-env");
      assert.equal(process.env.SHARED_VALUE, "mode-local");
      assert.equal(process.env.LOCAL_ONLY, "1");
      assert.equal(process.env.MODE_ONLY, "development");
      assert.equal(process.env.MODE_LOCAL_ONLY, "1");
    });
  });

  it("does not override variables that already exist in the shell environment", () => {
    withTempWorkspace((workspaceRoot) => {
      writeFileSync(join(workspaceRoot, ".env"), "DATABASE_URL=postgres://from-env\n");
      writeFileSync(join(workspaceRoot, ".env.local"), "DATABASE_URL=postgres://from-local\n");
      process.env.DATABASE_URL = "postgres://from-shell";

      loadWorkspaceEnv({ workspaceRoot });

      assert.equal(process.env.DATABASE_URL, "postgres://from-shell");
    });
  });

  it("returns the candidate env paths even when files are missing", () => {
    withTempWorkspace((workspaceRoot) => {
      process.env.NODE_ENV = "test";

      const envPaths = resolveWorkspaceEnvPaths({ workspaceRoot });

      assert.deepEqual(
        envPaths.map((entry) => entry.slice(workspaceRoot.length + 1)),
        [".env", ".env.test", ".env.local", ".env.test.local"],
      );
      assert.deepEqual(loadWorkspaceEnv({ workspaceRoot }), []);
    });
  });
});
