#!/usr/bin/env node
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { PrismaClient } from "@prisma/client";
import { rotateLocalKek } from "../security/localKekRotation.js";

const execFileAsync = promisify(execFile);

async function main(): Promise<void> {
  if (process.getuid?.() !== 0) {
    throw new Error("local KEK rotation must run as root");
  }
  await requireStoppedService();
  const keyringFile = parseKeyringFile(process.argv.slice(2));
  const databaseUrl = process.env["DATABASE_URL"]?.trim();
  if (databaseUrl === undefined || databaseUrl === "") {
    throw new Error("DATABASE_URL is required for local KEK rotation");
  }
  const prisma = new PrismaClient({ datasources: { db: { url: databaseUrl } }, log: [] });
  try {
    const result = await rotateLocalKek({ keyringFile, prisma });
    console.log(
      `[secret-kek] active=${result.activeKeyId} rewrapped=${result.rewrapped} verified=${result.verified}`,
    );
    console.log("[secret-kek] back up the updated keyring separately before retiring any previous key");
  } finally {
    await prisma.$disconnect();
  }
}

async function requireStoppedService(): Promise<void> {
  const serviceUnit = readServiceUnit();
  let activeState: string;
  try {
    const { stdout } = await execFileAsync(
      "systemctl",
      ["show", "--property=ActiveState", "--value", serviceUnit],
      { timeout: 10_000 },
    );
    activeState = stdout.trim();
  } catch {
    throw new Error(`cannot verify that ${serviceUnit} is stopped`);
  }
  if (activeState !== "inactive" && activeState !== "failed") {
    throw new Error(`${serviceUnit} must be stopped before local KEK rotation; state=${activeState || "unknown"}`);
  }
}

function readServiceUnit(): string {
  const serviceUnit = process.env["HUB_SYSTEMD_UNIT"]?.trim();
  if (serviceUnit === undefined || !/^cph-hub-[a-z0-9][a-z0-9-]*\.service$/.test(serviceUnit)) {
    throw new Error("HUB_SYSTEMD_UNIT must name this Silo unit (cph-hub-<instance>.service)");
  }
  return serviceUnit;
}

function parseKeyringFile(argv: readonly string[]): string {
  if (argv.length !== 2 || argv[0] !== "--keyring-file" || argv[1] === undefined || argv[1] === "") {
    throw new Error("usage: rotate-secret-kek --keyring-file /absolute/path/to/secret-keyring.json");
  }
  return argv[1];
}

main().catch((error: unknown) => {
  console.error(`[secret-kek] failed: ${error instanceof Error ? error.message : String(error)}`);
  process.exitCode = 1;
});
