import pg from "pg";
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";

export function createDb(connectionString = process.env.DATABASE_URL) {
	if (!connectionString) throw new Error("DATABASE_URL is required");
	const pool = new pg.Pool({
		connectionString,
		max: 10,
		ssl:
			process.env.DATABASE_SSL === "true"
				? { rejectUnauthorized: true }
				: undefined,
	});
	return {
		query: (...args) => pool.query(...args),
		connect: () => pool.connect(),
		close: () => pool.end(),
	};
}

/** Apply each versioned SQL file once; failed migrations are not recorded. */
export async function migrate(db) {
	await db.query(
		"CREATE TABLE IF NOT EXISTS schema_migrations (filename text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now())",
	);
	const directory = path.join(
		path.dirname(fileURLToPath(import.meta.url)),
		"..",
		"db",
		"migrations",
	);
	const files = (await fs.readdir(directory))
		.filter((file) => file.endsWith(".sql"))
		.sort();
	for (const filename of files) {
		if (
			(
				await db.query("SELECT 1 FROM schema_migrations WHERE filename=$1", [
					filename,
				])
			).rowCount
		)
			continue;
		const sql = await fs.readFile(path.join(directory, filename), "utf8");
		await db.query("BEGIN");
		try {
			await db.query(sql);
			await db.query("INSERT INTO schema_migrations(filename) VALUES($1)", [
				filename,
			]);
			await db.query("COMMIT");
		} catch (error) {
			await db.query("ROLLBACK");
			throw error;
		}
	}
}
