#!/usr/bin/env node
import { basename, dirname, join, resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import {
  commandToString,
  ensureParentDir,
  flag,
  option,
  parseArgs,
  readEnvFile,
  runCommand,
  timestampSlug,
} from './ops-utils.mjs';

function usage() {
  return `Usage: node scripts/backup-server-data.mjs [options]

Backs up the server_data Docker volume that stores runtime AI provider config.

Options:
  --env-file <path>       Compose env file used to derive COMPOSE_PROJECT_NAME
                          (default: .env.production)
  --volume <name>         Explicit Docker volume name
  --backup-dir <path>     Directory for generated backups (default: backups/server-data)
  --output <path>         Exact output .tgz path
  --image <name>          Utility image (default: alpine:3.20)
  --dry-run               Print the docker run command without writing a file
  --help                  Show this help
`;
}

function buildOptions(argv) {
  const args = parseArgs(argv);
  if (flag(args, 'help')) return { help: true };

  const envFile = option(args, 'env-file', '.env.production');
  const env = readEnvFile(envFile, { optional: flag(args, 'dry-run') });
  const projectName = env.COMPOSE_PROJECT_NAME || 'ftb_pm';
  const volume = option(args, 'volume', `${projectName}_server_data`);
  const backupDir = option(args, 'backup-dir', 'backups/server-data');
  const output = option(
    args,
    'output',
    join(backupDir, `${volume}-${timestampSlug()}.tgz`),
  );

  return {
    help: false,
    dryRun: flag(args, 'dry-run'),
    image: option(args, 'image', 'alpine:3.20'),
    volume,
    output: resolve(output),
  };
}

export function buildServerDataBackupCommand(options) {
  const outputDir = dirname(options.output);
  const outputName = basename(options.output);
  return [
    'docker',
    'run',
    '--rm',
    '-v',
    `${options.volume}:/data:ro`,
    '-v',
    `${outputDir}:/backup`,
    options.image,
    'sh',
    '-lc',
    `tar -czf /backup/${outputName} -C /data .`,
  ];
}

export async function main(argv = process.argv.slice(2)) {
  const options = buildOptions(argv);
  if (options.help) {
    process.stdout.write(usage());
    return;
  }

  const command = buildServerDataBackupCommand(options);
  if (options.dryRun) {
    process.stdout.write(`[dry-run] server_data backup would write: ${options.output}\n`);
    process.stdout.write(`${commandToString(command)}\n`);
    return;
  }

  ensureParentDir(options.output);
  await runCommand(command);
  process.stdout.write(`server_data backup written: ${options.output}\n`);
}

if (import.meta.url === pathToFileURL(process.argv[1]).href) {
  main().catch((error) => {
    process.stderr.write(`${error.message}\n`);
    process.exit(1);
  });
}

