import { mkdir } from "node:fs/promises";
import { join, resolve } from "node:path";
import { loadProjectEnv } from "../src/server/load-env.ts";
import { createSecretCodec } from "../src/server/secrets/secret-codec.ts";
import { createRuntimeDatabase } from "../src/server/storage/drizzle/create-runtime-database.ts";

loadProjectEnv();

const command = process.argv[2];
const options = parseOptions(process.argv.slice(3));
const dataDir = resolve(options.dataDir ?? process.env.OOMOL_CONNECT_DATA_DIR ?? join(process.cwd(), "data"));
const secretCodec = createSecretCodec(process.env.OOMOL_CONNECT_ENCRYPTION_KEY);
const driver = process.env.OOMOL_CONNECT_DB_DRIVER ?? "sqlite";

if (!command || !["reset", "rotate-key"].includes(command)) {
  printUsageAndExit();
}

if (driver !== "sqlite" && options.dataDir) {
  console.warn(`--data-dir is ignored when OOMOL_CONNECT_DB_DRIVER=${driver}.`);
}

await mkdir(dataDir, { recursive: true });

if (command === "rotate-key") {
  const nextEncryptionKey = process.env.OOMOL_CONNECT_NEW_ENCRYPTION_KEY;
  if (!nextEncryptionKey && options.plain !== "true") {
    throw new Error("rotate-key requires OOMOL_CONNECT_NEW_ENCRYPTION_KEY unless --plain is set.");
  }
  const database = await createRuntimeDatabase({ dataDir, secretCodec });
  try {
    await database.rotateSecretCodec(createSecretCodec(options.plain === "true" ? undefined : nextEncryptionKey));
    console.log(`Rotated runtime secret encryption (${driver}).`);
  } finally {
    await database.close();
  }
} else {
  const database = await createRuntimeDatabase({ dataDir, secretCodec });
  try {
    if (options.yes !== "true") {
      throw new Error("reset requires --yes.");
    }
    await database.resetRuntimeData();
    console.log(`Reset runtime data (${driver}).`);
  } finally {
    await database.close();
  }
}

type RuntimeDataCommandOptions = {
  dataDir?: string;
  plain?: string;
  yes?: string;
};

function parseOptions(args: string[]): RuntimeDataCommandOptions {
  const options: RuntimeDataCommandOptions = {};
  for (let index = 0; index < args.length; index += 1) {
    const arg = args[index];
    if (arg === "--yes") {
      options.yes = "true";
      continue;
    }
    if (arg === "--plain") {
      options.plain = "true";
      continue;
    }

    const value = args[index + 1];
    if (!value) {
      throw new Error(`${arg} requires a value.`);
    }

    if (arg === "--data-dir") {
      options.dataDir = value;
    } else {
      throw new Error(`Unknown option: ${arg}.`);
    }
    index += 1;
  }

  return options;
}

function printUsageAndExit(): never {
  console.error(`Usage:
  node scripts/runtime-data.ts reset --yes [--data-dir ./data]
  node scripts/runtime-data.ts rotate-key [--plain] [--data-dir ./data]

Environment:
  OOMOL_CONNECT_DB_DRIVER=sqlite|postgres|mysql (default sqlite)
  OOMOL_CONNECT_DATABASE_URL=... (required for postgres/mysql)
  OOMOL_CONNECT_ENCRYPTION_KEY / OOMOL_CONNECT_NEW_ENCRYPTION_KEY
  OOMOL_CONNECT_DATA_DIR (sqlite only; ignored for postgres/mysql with a warning when --data-dir is set)
`);
  process.exit(1);
}
