// Tests for server/src/localdb/runtime.ts and runtime-fetch.ts (PG Task 2) —
// the half that touches the filesystem, the network and child processes.
//
// Everything here runs against a throwaway directory under the OS temp folder,
// never the real %LOCALAPPDATA%\BalancedSum: these tests run initdb and start
// database servers, and a test suite that can reach the machine's actual books
// is a test suite that will eventually delete them.
//
// TWO TIERS, and the split is deliberate:
//
//   Tier 1 (always runs) — the download-and-verify path, driven by a local HTTP
//     server and a synthetic manifest. No PostgreSQL involved. This is where the
//     checksum gate, the HTTP failures and the "nothing was installed" promises
//     are asserted, because those are the paths a user hits on a bad day and
//     they must not be the ones that only get exercised when a 25 MB tarball
//     happens to be sitting in the working tree.
//
//   Tier 2 (skips cleanly) — the real 16.10 binaries: extract, initdb, start,
//     connect, stop. Needs the staged runtime tarball, which is gitignored (a
//     25 MB binary never enters git — see scripts/stage-pg-runtime.ts). When it
//     isn't there, the whole describe() is skipped WITH A PRINTED REASON, so a
//     clean checkout reports "not run" rather than a silent pass.

import { describe, it, expect, beforeAll, afterAll } from "vitest";
import http from "node:http";
import net from "node:net";
import os from "node:os";
import path from "node:path";
import { createReadStream, existsSync, statSync } from "node:fs";
import { mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { brotliCompressSync } from "node:zlib";
import { Client } from "pg";

import { resolveLayout, binaryPath, type LocalDbLayout } from "../../server/src/localdb/paths.js";
import { SHIPPED_POSTGRES_VERSION, type ArtifactEntry } from "../../server/src/localdb/manifest.js";
import { MAINTENANCE_DATABASE, DEFAULT_PORT } from "../../server/src/localdb/instance.js";
import { type PlatformId } from "../../server/src/localdb/platform.js";
import { REQUIRED_BINARIES, LocalDbError } from "../../server/src/localdb/runtime-facts.js";
import {
  ensureRuntime, isRuntimeInstalled, resolveTarExecutable,
  type RuntimeLogger,
} from "../../server/src/localdb/runtime-fetch.js";
import {
  ensureCluster, start, stop, isRunning, readInstance, readSecret,
  adminConnection, resolveCurrentLayout,
} from "../../server/src/localdb/runtime.js";

// ---------------------------------------------------------------------------
// fixtures
// ---------------------------------------------------------------------------

const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");

/** The tarball `npm run pg:stage` produces. Gitignored, so present on a
 *  maintainer's machine and absent on a fresh checkout. */
const STAGED_TARBALL = path.join(
  repoRoot, "site", "public", "runtime", `postgresql-${SHIPPED_POSTGRES_VERSION}-win32-x64.tar.xz`);

/** The digest RUNTIME_MANIFEST carries for that file. Restated here rather than
 *  imported so a test that serves the real bytes proves the real manifest value
 *  is right, instead of proving a constant equals itself. */
const STAGED_TARBALL_SHA256 = "27f4900cd8289a75466d1bcd09f6ebce051d59f1dbfda33995644a90b2a28db6";

const REAL_RUNTIME_AVAILABLE = process.platform === "win32" && existsSync(STAGED_TARBALL);
if (!REAL_RUNTIME_AVAILABLE) {
  console.warn(
    `[localdb-runtime] SKIPPING the real-PostgreSQL tests: ${
      process.platform !== "win32"
        ? `this is ${process.platform}, and only the Windows runtime artifact has been built`
        : `no staged runtime at ${STAGED_TARBALL} — run \`npm run pg:stage\` to build it`
    }.`,
  );
}

/** Collects what a user would have been told, instead of printing it. */
function captureLogger(): RuntimeLogger & { lines: string[] } {
  const lines: string[] = [];
  return { lines, info: (m) => lines.push(m), warn: (m) => lines.push(m) };
}

const silent: RuntimeLogger = { info: () => {}, warn: () => {} };

async function scratchLayout(): Promise<{ layout: LocalDbLayout; cleanup: () => Promise<void> }> {
  const root = await mkdtemp(path.join(os.tmpdir(), "bsum-localdb-"));
  const result = resolveLayout("win32-x64", { LOCALAPPDATA: root }, SHIPPED_POSTGRES_VERSION);
  if (!result.ok) throw new Error(result.message);
  return { layout: result.layout, cleanup: () => rm(root, { recursive: true, force: true }) };
}

/** A one-file HTTP server. Returns the URL it is serving `body` at. `body` may
 *  be a path (streamed, with Content-Length) or a Buffer. */
async function serve(
  body: string | Buffer, options: { status?: number; truncate?: boolean; brotli?: boolean } = {},
): Promise<{ url: string; close: () => Promise<void>; hits: () => number }> {
  let hits = 0;
  const server = http.createServer((_req, res) => {
    hits += 1;
    if (options.status && options.status !== 200) {
      res.writeHead(options.status);
      res.end("nope");
      return;
    }
    // What a CDN actually does, which no local test server did until this
    // shipped and broke every first launch. Netlify serves the runtime with
    // `Content-Encoding: br` to anything advertising brotli — Node's fetch
    // does, by default — so Content-Length describes the COMPRESSED transfer
    // while fetch hands the caller the decompressed original. Any code that
    // compares "bytes I received" against Content-Length is then comparing two
    // different quantities.
    if (options.brotli && typeof body !== "string") {
      const compressed = brotliCompressSync(body);
      res.writeHead(200, {
        "content-encoding": "br",
        "content-length": String(compressed.length),
      });
      res.end(compressed);
      return;
    }
    if (typeof body === "string") {
      const size = statSync(body).size;
      // Promises the full length and then delivers a fraction of it — the
      // shape a proxy closing a connection produces.
      res.writeHead(200, { "content-length": String(size) });
      createReadStream(body, options.truncate ? { start: 0, end: 1023 } : undefined)
        .pipe(res);
      return;
    }
    res.writeHead(200, { "content-length": String(body.length) });
    res.end(body);
  });
  await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
  const address = server.address();
  const port = typeof address === "object" && address ? address.port : 0;
  return {
    url: `http://127.0.0.1:${port}/postgresql-${SHIPPED_POSTGRES_VERSION}-win32-x64.tar.xz`,
    close: () => new Promise<void>((resolve) => server.close(() => resolve())),
    hits: () => hits,
  };
}

function manifestFor(url: string, sha256: string, sizeBytes: number): Readonly<Record<PlatformId, ArtifactEntry>> {
  return {
    "win32-x64": {
      state: "published",
      artifact: { url, sha256, sizeBytes, postgresVersion: SHIPPED_POSTGRES_VERSION },
    },
    "darwin-arm64": { state: "not-built", why: "no Mac build yet" },
    "darwin-x64": { state: "not-built", why: "no Mac build yet" },
  };
}

/** An OS-assigned free port, so a test never fights the developer's own
 *  PostgreSQL — or the 54329 a real install would be using. */
function freePort(): Promise<number> {
  return new Promise((resolve, reject) => {
    const probe = net.createServer();
    probe.on("error", reject);
    probe.listen(0, "127.0.0.1", () => {
      const address = probe.address();
      const port = typeof address === "object" && address ? address.port : 0;
      probe.close(() => resolve(port));
    });
  });
}

// ---------------------------------------------------------------------------
// resolveCurrentLayout / resolveTarExecutable
// ---------------------------------------------------------------------------

describe("resolveCurrentLayout", () => {
  it("passes platform.ts's refusal through verbatim rather than rewriting it", () => {
    // Two wordings of the same refusal is how one of them ends up stale.
    try {
      resolveCurrentLayout({ nodePlatform: "linux", nodeArch: "x64", env: {} });
      expect.unreachable("Linux must not resolve to a layout");
    } catch (err) {
      expect(err).toBeInstanceOf(LocalDbError);
      expect((err as LocalDbError).code).toBe("unsupported-platform");
      expect((err as LocalDbError).message).toContain("Linux");
    }
  });

  it("refuses rather than guessing when the environment won't say where app data goes", () => {
    try {
      resolveCurrentLayout({ nodePlatform: "win32", nodeArch: "x64", env: {} });
      expect.unreachable("an empty LOCALAPPDATA must not produce a layout");
    } catch (err) {
      expect((err as LocalDbError).code).toBe("no-app-data-root");
    }
  });

  it("builds the real layout for this machine when it can", () => {
    const layout = resolveCurrentLayout({
      nodePlatform: "win32", nodeArch: "x64", env: { LOCALAPPDATA: "C:\\Users\\x\\AppData\\Local" },
    });
    expect(layout.dataDir).toBe("C:\\Users\\x\\AppData\\Local\\BalancedSum\\data\\pg16");
    expect(layout.postgresVersion).toBe(SHIPPED_POSTGRES_VERSION);
  });
});

describe("resolveTarExecutable", () => {
  it("resolves an ABSOLUTE System32 path on Windows, never a bare `tar`", () => {
    // A bare `tar` on a developer's PATH is very often Git-for-Windows' GNU
    // tar, which cannot read what we ship, and whose failure looks exactly like
    // a corrupt download.
    const tar = resolveTarExecutable("win32-x64", { SystemRoot: process.env.SystemRoot });
    expect(path.win32.isAbsolute(tar)).toBe(true);
    expect(tar.toLowerCase()).toContain("system32");
    expect(tar.toLowerCase().endsWith("tar.exe")).toBe(true);
  });

  it("explains in English when Windows is too old to have it", () => {
    try {
      resolveTarExecutable("win32-x64", { SystemRoot: "Z:\\nope" });
      expect.unreachable("a missing tar.exe must not resolve");
    } catch (err) {
      expect((err as LocalDbError).code).toBe("tar-unavailable");
      expect((err as LocalDbError).message).toMatch(/newer Windows/);
      expect((err as LocalDbError).message).not.toMatch(/ENOENT/);
    }
  });
});

// ---------------------------------------------------------------------------
// Tier 1 — ensureRuntime, without any PostgreSQL involved
// ---------------------------------------------------------------------------

describe("ensureRuntime", () => {
  it("does nothing at all when all nine executables are already there", async () => {
    const { layout, cleanup } = await scratchLayout();
    try {
      await mkdir(layout.binDir, { recursive: true });
      for (const binary of REQUIRED_BINARIES) {
        await writeFile(path.join(layout.binDir, `${binary}.exe`), "not really an exe");
      }

      // The every-launch-after-the-first path. If it fetches, hashes, or even
      // looks for tar, the launch gets slower forever — so the proof is that a
      // fetch which THROWS is never called.
      const result = await ensureRuntime(layout, {
        log: silent,
        fetchImpl: (() => { throw new Error("must not fetch"); }) as unknown as typeof fetch,
        tarExecutable: "Z:\\definitely-not-here.exe",
      });

      expect(result.action).toBe("already-present");
      expect(await isRuntimeInstalled(layout)).toBe(true);
    } finally {
      await cleanup();
    }
  });

  it("re-downloads when even one executable is missing", async () => {
    const { layout, cleanup } = await scratchLayout();
    try {
      await mkdir(layout.binDir, { recursive: true });
      for (const binary of REQUIRED_BINARIES) {
        if (binary === "pg_restore") continue; // the one nobody notices until RESTORE.md matters
        await writeFile(path.join(layout.binDir, `${binary}.exe`), "x");
      }
      expect(await isRuntimeInstalled(layout)).toBe(false);

      // Proven by getting as far as the download rather than returning early.
      const server = await serve(Buffer.from("not a tarball"));
      try {
        await expect(ensureRuntime(layout, {
          log: silent,
          manifest: manifestFor(server.url, "a".repeat(64), 13),
        })).rejects.toThrow(/didn't arrive intact/);
        expect(server.hits()).toBe(1);
      } finally {
        await server.close();
      }
    } finally {
      await cleanup();
    }
  });

  it("refuses to adopt a cluster it did not create when something else holds its port", async () => {
    // REGRESSION, found by installing the published 2.0.1 on a machine that
    // already had one. The new install created its own cluster, saw port 54329
    // answering, announced "the database is already running", and tried to log
    // in to the OTHER installation with its own generated password. It failed
    // authentication — which was luck, not design: two installs share the
    // superuser NAME, and only the randomness of the password stood between
    // that and an application pointed at a stranger's books.
    //
    // The distinguishing fact is that OUR data directory has no postmaster.pid.
    // Something is on the port; it just isn't ours.
    // It has to be a REAL PostgreSQL holding the port. A bare TCP listener does
    // not reproduce this: the running-or-not judgement asks pg_isready, which
    // refuses anything that cannot speak the protocol, so a decoy socket reads
    // as "nothing there" and the code goes on to start its own server. That is
    // correct behaviour, and it is why this test uses the cluster the test
    // harness already requires to be running (tests/helpers/test-db-admin.ts)
    // rather than inventing a fake one.
    const realLayout = resolveCurrentLayout({
      nodePlatform: process.platform, nodeArch: process.arch, env: process.env,
    });
    const realInstance = JSON.parse(await readFile(realLayout.instanceFile, "utf8")) as { port: number };

    const scratch = await scratchLayout();
    const cleanup = scratch.cleanup;
    // Its own data directory, but the REAL binaries: a second installation has
    // downloaded its own copy of PostgreSQL, and the running-or-not judgement
    // is made by running pg_isready out of it. With an empty runtime directory
    // that probe cannot run at all, the port reads as silent, and the test
    // proves nothing while appearing to.
    const layout = { ...scratch.layout, binDir: realLayout.binDir };
    try {
      // A second installation: its own data directory, no postmaster.pid of its
      // own, and an instance.json naming the port the first one is on.
      await mkdir(layout.dataDir, { recursive: true });
      await writeFile(layout.instanceFile, JSON.stringify({
        formatVersion: 1, postgresVersion: SHIPPED_POSTGRES_VERSION, postgresMajor: 16,
        platform: "win32-x64", port: realInstance.port, createdAt: new Date().toISOString(),
        createdByAppVersion: "2.0.1",
      }));

      const error = await start(layout, { log: silent }).catch((e: unknown) => e as LocalDbError);
      expect(error).toBeInstanceOf(LocalDbError);
      expect((error as LocalDbError).code).toBe("port-in-use");
      expect((error as LocalDbError).message).toContain(String(realInstance.port));
      // The whole point: it must not report success and hand back a port.
      expect((error as LocalDbError).message).not.toMatch(/already running/i);
      // And it must not have started anything of its own in the scratch root.
      expect(existsSync(layout.postmasterPidFile)).toBe(false);
    } finally {
      await cleanup();
    }
  });

  it("survives a CDN that compresses the transfer — the bug that broke every 2.0.0 first launch", async () => {
    // REGRESSION. Netlify serves the runtime with `Content-Encoding: br` to any
    // client advertising brotli, which Node's fetch does by default. Its
    // Content-Length then describes the compressed transfer (25,918,026 bytes
    // on the real file) while fetch delivers the decompressed original
    // (25,915,316). The old code compared the two and declared a flawless
    // download truncated: 100% progress, correct digest, and the user told
    // their internet connection had dropped. It failed 100% of first launches
    // and no local test caught it, because every test server here served the
    // bytes uncompressed with an honest Content-Length.
    //
    // The assertion is deliberately about WHICH gate rejects it. Serving a body
    // whose digest is wrong, the run must fail on the checksum — which can only
    // happen if it got PAST the length check. A "download stopped part way"
    // here is the regression, returned.
    const { layout, cleanup } = await scratchLayout();
    const server = await serve(Buffer.from("a compressible little body ".repeat(200)), { brotli: true });
    try {
      const error = await ensureRuntime(layout, {
        log: silent,
        manifest: manifestFor(server.url, "e".repeat(64), 5400),
      }).catch((e: unknown) => e as LocalDbError);

      expect((error as LocalDbError).code).toBe("checksum-mismatch");
      expect((error as LocalDbError).message).not.toMatch(/stopped part way/i);
    } finally {
      await server.close();
      await cleanup();
    }
  });

  it("refuses with the macOS explanation instead of attempting a broken download", async () => {
    const { layout, cleanup } = await scratchLayout();
    try {
      const macLayout = { ...layout, platform: "darwin-arm64" as PlatformId };
      await expect(ensureRuntime(macLayout, { log: silent })).rejects.toMatchObject({
        code: "runtime-unavailable",
      });
      await expect(ensureRuntime(macLayout, { log: silent })).rejects.toThrow(/Mac/);
    } finally {
      await cleanup();
    }
  });

  it("throws away a file whose checksum doesn't match and installs NOTHING", async () => {
    const { layout, cleanup } = await scratchLayout();
    const server = await serve(Buffer.from("these are not the bytes you are looking for"));
    try {
      const error = await ensureRuntime(layout, {
        log: silent,
        manifest: manifestFor(server.url, "b".repeat(64), 42),
      }).catch((e: unknown) => e as LocalDbError);

      expect(error).toBeInstanceOf(LocalDbError);
      expect((error as LocalDbError).code).toBe("checksum-mismatch");
      expect((error as LocalDbError).message).toMatch(/nothing was installed/i);
      // The gate is only a gate if the rejected file is gone. Nothing may be
      // left in runtime/ for a later run to find and believe.
      expect(existsSync(layout.runtimeDir)).toBe(false);
      expect(await leftovers(layout)).toEqual([]);
    } finally {
      await server.close();
      await cleanup();
    }
  });

  it("says the download failed, in English, when the host answers with an error", async () => {
    const { layout, cleanup } = await scratchLayout();
    const server = await serve(Buffer.from(""), { status: 404 });
    try {
      const error = await ensureRuntime(layout, {
        log: silent,
        manifest: manifestFor(server.url, "c".repeat(64), 1),
      }).catch((e: unknown) => e as LocalDbError);

      expect((error as LocalDbError).code).toBe("download-failed");
      expect((error as LocalDbError).message).toMatch(/balancedsum\.com/);
      expect((error as LocalDbError).message).not.toMatch(/404|HTTP/);
      // The status IS recorded — in detail, where it belongs.
      expect((error as LocalDbError).detail).toContain("404");
    } finally {
      await server.close();
      await cleanup();
    }
  });

  it("says the download failed when nothing is listening at all", async () => {
    const { layout, cleanup } = await scratchLayout();
    try {
      const port = await freePort(); // free, therefore nothing is on it
      const error = await ensureRuntime(layout, {
        log: silent,
        manifest: manifestFor(`http://127.0.0.1:${port}/x.tar.xz`, "d".repeat(64), 1),
      }).catch((e: unknown) => e as LocalDbError);

      expect((error as LocalDbError).code).toBe("download-failed");
      expect((error as LocalDbError).message).toMatch(/is online/);
    } finally {
      await cleanup();
    }
  });

  // Skipped rather than quietly passing when the tarball isn't here: this one
  // needs a body big enough that the transport gives up mid-stream, and a test
  // that asserts nothing must not report itself as green.
  it.skipIf(!REAL_RUNTIME_AVAILABLE)("calls a transfer that stopped part way through what it is", async () => {
    const { layout, cleanup } = await scratchLayout();
    const server = await serve(STAGED_TARBALL, { truncate: true });
    try {
      const error = await ensureRuntime(layout, {
        log: silent,
        manifest: manifestFor(server.url, STAGED_TARBALL_SHA256, statSync(STAGED_TARBALL).size),
      }).catch((e: unknown) => e as LocalDbError);

      // A truncated transfer would ALSO fail the digest check a moment later —
      // but with a message about hex strings instead of the truth. Whether the
      // HTTP client notices the short body itself or we catch it on the byte
      // count, the user reads the same sentence.
      expect((error as LocalDbError).code).toBe("download-failed");
      expect((error as LocalDbError).message).toMatch(/stopped part way through/);
      expect(existsSync(layout.runtimeDir)).toBe(false);
      expect(await leftovers(layout)).toEqual([]);
    } finally {
      await server.close();
      await cleanup();
    }
  }, 60_000);
});

/** Anything left in runtime/ besides the finished directory: a stray download,
 *  a half-extracted staging tree. Should always be empty once a call returns,
 *  success or failure. */
async function leftovers(layout: LocalDbLayout): Promise<string[]> {
  const entries = await readdir(layout.runtimeRoot).catch(() => [] as string[]);
  return entries.filter((e) => e !== path.basename(layout.runtimeDir));
}

// ---------------------------------------------------------------------------
// Tier 2 — the real 16.10 binaries
// ---------------------------------------------------------------------------

describe.skipIf(!REAL_RUNTIME_AVAILABLE)("the real PostgreSQL runtime", () => {
  let layout: LocalDbLayout;
  let cleanup: () => Promise<void>;
  let server: Awaited<ReturnType<typeof serve>>;
  let port: number;

  beforeAll(async () => {
    ({ layout, cleanup } = await scratchLayout());
    server = await serve(STAGED_TARBALL);
    port = await freePort();
  }, 120_000);

  afterAll(async () => {
    // Never leave a detached postmaster behind holding a temp directory open.
    await stop(layout, { log: silent }).catch(() => {});
    await server?.close();
    await cleanup?.();
  }, 120_000);

  it("downloads, verifies and unpacks a complete runtime — and is a no-op the second time",
    async () => {
      const log = captureLogger();
      const first = await ensureRuntime(layout, {
        log, manifest: manifestFor(server.url, STAGED_TARBALL_SHA256, statSync(STAGED_TARBALL).size),
      });
      expect(first.action).toBe("downloaded");

      // Every one of the nine, actually on disk, at the path binaryPath() names.
      for (const binary of REQUIRED_BINARIES) {
        expect(existsSync(binaryPath(layout, binary))).toBe(true);
      }
      // lib/ and share/ too: initdb reads share/, and postgres.exe will not
      // load without the DLLs beside it.
      expect(existsSync(layout.libDir)).toBe(true);
      expect(existsSync(layout.shareDir)).toBe(true);
      expect(await leftovers(layout)).toEqual([]);
      expect(log.lines.join("\n")).toMatch(/verified its checksum/);

      const second = await ensureRuntime(layout, {
        log: silent,
        fetchImpl: (() => { throw new Error("must not re-download"); }) as unknown as typeof fetch,
      });
      expect(second.action).toBe("already-present");
    }, 300_000);

  it("initdbs exactly once, writes the password 0600, and records the instance AFTER",
    async () => {
      const created = await ensureCluster(layout, { log: silent, port, appVersion: "test" });
      expect(created.action).toBe("created");
      expect(created.instance.port).toBe(port);
      expect(created.instance.postgresMajor).toBe(16);

      // The cluster is real: PostgreSQL's own record of it exists.
      expect(existsSync(path.join(layout.dataDir, "PG_VERSION"))).toBe(true);
      expect((await readFile(path.join(layout.dataDir, "PG_VERSION"), "utf8")).trim()).toBe("16");

      const secret = await readSecret(layout);
      expect(secret).toHaveLength(32);
      expect(secret).toMatch(/^[A-Za-z0-9]+$/);
      // Exactly the password, no trailing newline: initdb --pwfile reads the
      // first line, and bytes-on-disk == password means nothing to parse.
      expect(await readFile(layout.secretFile, "utf8")).toBe(secret);

      // scram-sha-256 for BOTH local and host, per the decisions document.
      const hba = await readFile(path.join(layout.dataDir, "pg_hba.conf"), "utf8");
      const rules = hba.split(/\r?\n/).filter((l) => l.trim() && !l.trim().startsWith("#"));
      expect(rules.length).toBeGreaterThan(0);
      for (const rule of rules) expect(rule).toMatch(/scram-sha-256/);

      // Second call must NOT create a second set of books.
      const again = await ensureCluster(layout, { log: silent, port });
      expect(again.action).toBe("existing");
      expect(again.instance.createdAt).toBe(created.instance.createdAt);
    }, 300_000);

  it("starts, is reachable with the generated password, and stops", async () => {
    expect((await isRunning(layout)).running).toBe(false);

    const started = await start(layout, { log: silent });
    expect(started.action).toBe("started");
    if (started.action !== "started") return;
    expect(started.port).toBe(port);
    // The measured budget, honoured. (6.3s in the spike; ~3.5s here.)
    expect(started.durationMs).toBeLessThan(30_000);

    const status = await isRunning(layout);
    expect(status.running).toBe(true);
    expect(status.pid).toBe(started.pid);
    // The pid file is PARSED, not guessed at: line 1 pid, line 4 port.
    const pidFile = await readFile(layout.postmasterPidFile, "utf8");
    expect(pidFile.split(/\r?\n/)[0]).toBe(String(started.pid));
    expect(pidFile.split(/\r?\n/)[3]).toBe(String(port));

    // Starting again is a no-op, not a second postmaster.
    const again = await start(layout, { log: silent });
    expect(again.action).toBe("already-running");

    const connection = await adminConnection(layout, MAINTENANCE_DATABASE);
    // The password never appears in the loggable form.
    expect(connection.redactedUrl).toContain(":***@");
    expect(connection.redactedUrl).not.toContain(await readSecret(layout));

    const client = new Client({ connectionString: connection.url });
    // This test stops the cluster a few lines below. A pg Client with no
    // 'error' listener turns a server-side disconnect into an UNCAUGHT
    // EXCEPTION, which kills this vitest worker — silently, after its tests
    // have already passed, so the file's results simply vanish from the totals
    // with nothing reported. client.end() runs first and normally wins the
    // race, but "normally" is exactly the word that produces a heisenbug; see
    // tests/helpers/in-flight.ts's header for the same failure in another
    // costume.
    client.on("error", () => { /* the cluster is being shut down on purpose */ });
    await client.connect();
    try {
      const { rows } = await client.query<{ version: string; port: string }>(
        "select version() as version, current_setting('port') as port");
      expect(rows[0]?.version).toContain("PostgreSQL 16.10");
      expect(rows[0]?.port).toBe(String(port));

      // scram-sha-256 really is what the superuser's password is stored as —
      // asserting the initdb flag is one thing, asserting the outcome is
      // another.
      const auth = await client.query<{ rolpassword: string }>(
        "select rolpassword from pg_authid where rolname = 'postgres'");
      expect(auth.rows[0]?.rolpassword).toMatch(/^SCRAM-SHA-256\$/);

      // Loopback only, no Unix socket — the whole network posture.
      const settings = await client.query<{ name: string; setting: string }>(
        "select name, setting from pg_settings where name in ('listen_addresses','unix_socket_directories')");
      const byName = Object.fromEntries(settings.rows.map((r) => [r.name, r.setting]));
      expect(byName["listen_addresses"]).toBe("127.0.0.1");
      expect(byName["unix_socket_directories"]).toBe("");
    } finally {
      await client.end();
    }

    const stopped = await stop(layout, { log: silent });
    expect(stopped.action).toBe("stopped");
    expect((await isRunning(layout)).running).toBe(false);
    expect(await stop(layout, { log: silent })).toEqual({ action: "not-running" });
  }, 300_000);

  it("recovers from the stale postmaster.pid a power cut leaves behind", async () => {
    // Trap #2 in the decisions document: ORDINARY, not exceptional. A pid that
    // is not alive, in a file shaped exactly like the real thing.
    await writeFile(
      layout.postmasterPidFile,
      [
        "999999", layout.dataDir, String(Math.floor(Date.now() / 1000)), String(port),
        "", "127.0.0.1", "  4242001         42", "ready   ", "",
      ].join("\n"),
      "utf8",
    );

    const status = await isRunning(layout);
    expect(status.running).toBe(false);
    expect(status.verdict.state).toBe("stale");

    const log = captureLogger();
    const started = await start(layout, { log });
    expect(started.action).toBe("started");
    // Told plainly what happened; never asked to go and delete a file.
    expect(log.lines.join("\n")).toMatch(/leftover/i);
    expect(log.lines.join("\n")).not.toMatch(/postmaster\.pid/);

    await stop(layout, { log: silent });
  }, 300_000);

  it("gives a comprehensible message — not a race — when a second server is already there",
    async () => {
      await start(layout, { log: silent });
      try {
        // Two copies of the app launched at once. Contriving it takes a little
        // setup: a second layout over the SAME data directory but with its own
        // lock-file path, its own recorded port and its own log, so that our own
        // "is it already running" guard doesn't short-circuit the thing under test.
        // What is being asserted is the LAST line of defence — PostgreSQL's own
        // refusal — actually reaching the user instead of surfacing as a
        // timeout or a race.
        const rogueInstance = path.join(layout.root, "instance-second-copy.json");
        const rogueLog = path.join(layout.logsDir, "second-copy.log");
        const rogue: LocalDbLayout = {
          ...layout,
          postmasterPidFile: path.join(layout.dataDir, "second-copy.pid"),
          instanceFile: rogueInstance,
          logFile: rogueLog,
        };
        await writeFile(rogueInstance, JSON.stringify({
          formatVersion: 1, postgresVersion: SHIPPED_POSTGRES_VERSION, postgresMajor: 16,
          platform: "win32-x64", port: await freePort(), createdAt: new Date().toISOString(),
          createdByAppVersion: "test",
        }), "utf8");

        const error = await start(rogue, { log: silent, readyTimeoutMs: 25_000 })
          .catch((e: unknown) => e as LocalDbError);

        expect(error).toBeInstanceOf(LocalDbError);
        expect((error as LocalDbError).code).toBe("start-failed");
        // The answer is always in the log, so the log is what gets quoted.
        expect((error as LocalDbError).message).toMatch(/lock file "postmaster\.pid" already exists/);
        expect((error as LocalDbError).message).toMatch(/Is another postmaster/);
        expect((error as LocalDbError).message).toContain(rogueLog);
      } finally {
        await stop(layout, { log: silent });
      }
    }, 300_000);

  it("refuses to touch a cluster written by a NEWER PostgreSQL", async () => {
    // The one mismatch with no migration path in either direction — you cannot
    // un-write a schema. Faked by telling the layout it ships an older major
    // than the cluster on disk, which is exactly what shipping PG16 over a PG17
    // cluster looks like from here.
    const olderBuild: LocalDbLayout = { ...layout, postgresMajor: 15, postgresVersion: "15.6" };
    const error = await ensureCluster(olderBuild, { log: silent, port })
      .catch((e: unknown) => e as LocalDbError);

    expect((error as LocalDbError).code).toBe("cluster-version-mismatch");
    expect((error as LocalDbError).message).toMatch(/NEWER version/);
    expect((error as LocalDbError).message).toMatch(/nothing has been changed/i);
    // And the books are untouched: the real cluster still opens.
    expect((await ensureCluster(layout, { log: silent, port })).action).toBe("existing");
  }, 300_000);

  it("rebuilds a deleted instance.json instead of stranding the user's books", async () => {
    const before = await readInstance(layout);
    await rm(layout.instanceFile, { force: true });

    const log = captureLogger();
    const result = await ensureCluster(layout, { log, port: before.port, appVersion: "test" });
    expect(result.action).toBe("recorded");
    expect(result.instance.postgresMajor).toBe(before.postgresMajor);
    expect(result.instance.port).toBe(before.port);
    expect(log.lines.join("\n")).toMatch(/rebuilt it/i);

    // …but only because the password was still on disk. Without it there is
    // nothing to rebuild FROM, and creating an empty cluster beside real books
    // is the worst outcome available.
    const secret = await readFile(layout.secretFile, "utf8");
    await rm(layout.instanceFile, { force: true });
    await rm(layout.secretFile, { force: true });
    const error = await ensureCluster(layout, { log: silent, port })
      .catch((e: unknown) => e as LocalDbError);
    expect((error as LocalDbError).code).toBe("cluster-unrecorded");
    expect((error as LocalDbError).message).toMatch(/still there/i);

    await writeFile(layout.secretFile, secret, "utf8");
    await ensureCluster(layout, { log: silent, port: before.port, appVersion: "test" });
  }, 300_000);

  it("refuses to create a second set of books when the data directory has vanished", async () => {
    const { layout: fresh, cleanup: cleanFresh } = await scratchLayout();
    try {
      // instance.json says a database exists here; the folder does not. Running
      // initdb would look like a successful repair and would be the moment the
      // books stopped existing.
      await mkdir(fresh.root, { recursive: true });
      await writeFile(fresh.instanceFile, JSON.stringify({
        formatVersion: 1, postgresVersion: SHIPPED_POSTGRES_VERSION, postgresMajor: 16,
        platform: "win32-x64", port: DEFAULT_PORT, createdAt: new Date().toISOString(),
        createdByAppVersion: "1.0.0",
      }), "utf8");

      const error = await ensureCluster(fresh, { log: silent })
        .catch((e: unknown) => e as LocalDbError);
      expect((error as LocalDbError).code).toBe("cluster-missing");
      expect(existsSync(fresh.dataDir)).toBe(false);
    } finally {
      await cleanFresh();
    }
  }, 300_000);
});
