// `npm run db:reset` — DROP the development database and rebuild it from the
// migrations. Development only. It destroys everything in that database.
//
// THIS SCRIPT USED TO BE A LANDMINE. It defaulted to
// `postgres://postgres:postgres@localhost:5432/accounting` and ran
// `DROP DATABASE ... WITH (FORCE)` against whatever answered. That was safe
// only for as long as the thing on port 5432 was this project's Docker
// container. Docker was removed on 2026-08-08 and the bundled PostgreSQL
// deliberately listens on 54329 instead — precisely so it cannot collide with a
// developer's own PostgreSQL. Which means the old default no longer pointed at
// our database at all: it pointed at THEIRS, and dropped a database called
// `accounting` there if one existed.
//
// So the default is gone. This script now resolves exactly what the running
// application resolves (server/src/db.ts), and it prints which server and which
// database it is about to destroy before it does it.

import { Client } from "pg";
import { migrate } from "./migrate.js";
import { resolveDatabaseUrls } from "../server/src/db.js";
import { redactConnectionUrl } from "../server/src/localdb/instance.js";
import "dotenv/config";

const { admin: DATABASE_URL, source } = await resolveDatabaseUrls();

// The maintenance database on the SAME server as the database being reset.
// ADMIN_URL is honoured when set, but deriving it is what keeps "drop" and
// "the thing I resolved" on one server: taking the target from one place and
// the connection from another is how you drop the right name in the wrong
// cluster.
function maintenanceUrlFrom(databaseUrl: string): string {
  const url = new URL(databaseUrl);
  url.pathname = "/postgres";
  return url.toString();
}

const ADMIN_URL = process.env.ADMIN_URL?.trim() || maintenanceUrlFrom(DATABASE_URL);

const dbName = new URL(DATABASE_URL).pathname.slice(1);
if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(dbName)) {
  // Interpolated straight into DDL below, because DROP DATABASE takes no
  // parameters. Anything that isn't a plain identifier stops here rather than
  // being quoted and hoped for.
  console.error(`\n[db:reset] "${dbName}" is not a plain database identifier. Refusing.\n`);
  process.exit(1);
}

console.log(`[db:reset] Server:   ${redactConnectionUrl(ADMIN_URL)}  (${source})`);
console.log(`[db:reset] Dropping and rebuilding database "${dbName}".`);

const m = new Client({ connectionString: ADMIN_URL });
await m.connect();
try {
  await m.query(`DROP DATABASE IF EXISTS ${dbName} WITH (FORCE)`);
  await m.query(`CREATE DATABASE ${dbName}`);
} finally {
  await m.end();
}
await migrate(DATABASE_URL);
console.log(`reset ${dbName} and applied all migrations`);
