import { test, expect, afterEach } from "bun:test";
import { mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { loadAppConfig, resolveProfile, loadEnv } from "../src/index.ts";

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

test("resolveProfile: explicit > WRNEXUS_PROFILE > mode default", () => {
  delete process.env.WRNEXUS_PROFILE;
  expect(resolveProfile({ mode: "development" })).toBe("development");
  expect(resolveProfile({ mode: "production" })).toBe("production");
  expect(resolveProfile({ explicit: "uat", mode: "production" })).toBe("uat");
  process.env.WRNEXUS_PROFILE = "test";
  expect(resolveProfile({ mode: "production" })).toBe("test");
  expect(resolveProfile({ explicit: "uat" })).toBe("uat"); // explicit still wins
});

test("loadAppConfig deep-merges the active profile and strips `profiles`", async () => {
  const dir = mkdtempSync(join(tmpdir(), "wire-cfg-"));
  writeFileSync(
    join(dir, "wrnexus.config.mjs"),
    `export default {
      port: 3000,
      db: { driver: "sqlite", url: "file:./dev.db" },
      seo: { title: "Base", siteName: "App" },
      profiles: {
        prod: { db: { driver: "postgres", url: "postgres://prod" }, port: 8080 },
        uat: { seo: { title: "UAT" } },
      },
    };`,
  );

  const dev = await loadAppConfig(dir, "development");
  expect(dev.db).toEqual({ driver: "sqlite", url: "file:./dev.db" });
  expect((dev as { profiles?: unknown }).profiles).toBeUndefined();

  const prod = await loadAppConfig(dir, "prod");
  expect(prod.db).toEqual({ driver: "postgres", url: "postgres://prod" });
  expect(prod.port).toBe(8080);
  expect(prod.seo).toEqual({ title: "Base", siteName: "App" }); // untouched

  const uat = await loadAppConfig(dir, "uat");
  expect(uat.seo).toEqual({ title: "UAT", siteName: "App" }); // deep-merged
  expect(uat.db!.driver).toBe("sqlite");
});

test("loadEnv layers .env files by precedence; real env always wins", () => {
  const dir = mkdtempSync(join(tmpdir(), "wire-env-"));
  writeFileSync(join(dir, ".env"), 'BASE=1\nSHARED=base\n# a comment\nQUOTED="hi there"\n');
  writeFileSync(join(dir, ".env.prod"), "SHARED=prod\nPROD_ONLY=yes\nREALVAR=fromfile\n");
  writeFileSync(join(dir, ".env.prod.local"), "SHARED=local\n");

  process.env.REALVAR = "real"; // simulate a real environment variable
  try {
    const loaded = loadEnv(dir, "prod");
    expect(loaded.BASE).toBe("1");
    expect(process.env.BASE).toBe("1");
    expect(process.env.QUOTED).toBe("hi there"); // quotes stripped
    expect(process.env.SHARED).toBe("local"); // .env.prod.local beats .env.prod beats .env
    expect(process.env.PROD_ONLY).toBe("yes");
    expect(process.env.REALVAR).toBe("real"); // real env NOT overridden by a file
  } finally {
    for (const k of ["BASE", "SHARED", "PROD_ONLY", "QUOTED", "REALVAR"]) delete process.env[k];
  }
});
