#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
import "dotenv/config";

const args = process.argv.slice(2);

function getArg(name) {
  const index = args.indexOf(name);
  return index >= 0 ? args[index + 1] : undefined;
}

function hasFlag(name) {
  return args.includes(name);
}

function usage() {
  console.log(`Usage:
  node scripts/backup-production.mjs [--out ./backups] [--include-mosquitto] [--dry-run]

Creates a timestamped PostgreSQL custom-format dump. When --include-mosquitto is set,
copies Mosquitto passwd/ACL files if readable.
`);
}

if (hasFlag("--help") || hasFlag("-h")) {
  usage();
  process.exit(0);
}

const outDir = path.resolve(process.cwd(), getArg("--out") || process.env.BACKUP_DIR || "./backups");
const includeMosquitto = hasFlag("--include-mosquitto");
const dryRun = hasFlag("--dry-run");
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
const dbName = process.env.PGDATABASE || "qris_soundbox_platform";
const dbBackup = path.join(outDir, `${dbName}-${timestamp}.dump`);
const passwdFile = process.env.MOSQUITTO_PASSWD_FILE || "/etc/mosquitto/passwd";
const aclFile = process.env.MOSQUITTO_ACL_FILE || "/etc/mosquitto/acl";

fs.mkdirSync(outDir, { recursive: true });

const pgDumpArgs = ["-Fc", "-f", dbBackup];
if (process.env.DATABASE_URL) {
  pgDumpArgs.push(process.env.DATABASE_URL);
} else {
  pgDumpArgs.push("-h", process.env.PGHOST || "127.0.0.1");
  pgDumpArgs.push("-p", String(process.env.PGPORT || 5432));
  pgDumpArgs.push("-U", process.env.PGUSER || "postgres");
  pgDumpArgs.push(dbName);
}

const plan = {
  out_dir: outDir,
  database_backup: dbBackup,
  include_mosquitto: includeMosquitto,
  commands: [`pg_dump ${pgDumpArgs.map((arg) => (arg.includes(" ") ? JSON.stringify(arg) : arg)).join(" ")}`]
};

if (dryRun) {
  console.log(JSON.stringify({ dry_run: true, ...plan }, null, 2));
  process.exit(0);
}

const result = spawnSync("pg_dump", pgDumpArgs, {
  stdio: "inherit",
  env: process.env
});
if (result.status !== 0) {
  throw new Error(`pg_dump failed with status ${result.status}`);
}

const copied = [];
if (includeMosquitto) {
  for (const source of [passwdFile, aclFile]) {
    if (!fs.existsSync(source)) {
      continue;
    }
    const target = path.join(outDir, `${path.basename(source)}-${timestamp}`);
    fs.copyFileSync(source, target);
    copied.push({ source, target });
  }
}

console.log(JSON.stringify({ ok: true, ...plan, copied }, null, 2));
