import { basename } from "path";
import compact from "lodash/compact";
import { move } from "../api/move";
import { shellQuote } from "../cli";
import { chooseDsns } from "../internal/chooseDsns";
import { log, print, stdlog } from "../internal/logging";
import { dsnFromToShort } from "../internal/names";
import { normalizeDsns } from "../internal/normalizeDsns";
import type { Args } from "../internal/parseArgs";
import {
  isInTmuxSession,
  runInTmux,
  tryReattachToTmuxSession,
} from "../internal/runInTmux";

/**
 * Copies a PG from one database to another with no downtime.
 */
export async function actionCopy(args: Args): Promise<boolean> {
  await tryReattachToTmuxSession();

  const dsns = await normalizeDsns(args["dsns"]);

  let schema: string;
  if (args["schema"]) {
    schema = args["schema"];
  } else {
    throw "Please provide --schema, a schema name to copy";
  }

  const [fromDsns, fromWarnings] = chooseDsns({
    patterns: compact([args["from"]]),
    existingDsns: dsns,
    requireMatch: false,
  });
  if (fromDsns.length === 0) {
    throw "Please provide --from, source DB DSN, as postgresql://user:pass@host/db?options, or a DSN prefix";
  }

  const [toDsns, toWarnings] = chooseDsns({
    patterns: compact([args["to"]]),
    existingDsns: dsns,
    requireMatch: false,
  });
  if (toDsns.length === 0) {
    throw "Please provide --to, destination DB DSN, as postgresql://user:pass@host/db?options, or a DSN prefix";
  }

  const maxReplicationLagSec =
    Number(args["max-replication-lag-sec"] ?? "") || undefined;

  const wait = args["wait"];

  if (isInTmuxSession()) {
    const unpipe = stdlog.pipeToNewLogFile(`copy-${schema}`);
    try {
      log(
        "$ " +
          [basename(process.argv[1]), ...process.argv.slice(2)]
            .map(shellQuote)
            .join(" "),
      );

      for (const warning of [...fromWarnings, ...toWarnings]) {
        print(warning);
      }

      await move({
        schema,
        fromDsn: fromDsns[0],
        toDsn: toDsns[0],
        commitAction: null,
        maxReplicationLagSec,
        wait,
      });
    } finally {
      await unpipe();
    }
  } else {
    await runInTmux([
      [
        {
          key: schema.toString(),
          title: `schema ${schema} | ${dsnFromToShort(fromDsns[0], toDsns[0])}`,
          command: process.argv,
        },
      ],
    ]);
  }

  return true;
}
