import { NextRequest, NextResponse } from "next/server";
import { exec } from "child_process";
import { promisify } from "util";
import { writeFile, unlink, readFile } from "fs/promises";
import { tmpdir } from "os";
import { join } from "path";
import { randomBytes } from "crypto";

const execAsync = promisify(exec);

export async function POST(req: NextRequest) {
  const body = await req.json();
  const {
    commonName,
    organization = "",
    organizationalUnit = "",
    locality = "",
    state = "",
    country = "US",
    email = "",
    keyType = "RSA",
    keySize = "2048",
    curve = "prime256v1",
    signatureAlgorithm = "sha256",
    sans = [],
  } = body;

  if (!commonName) return NextResponse.json({ error: "commonName required" }, { status: 400 });

  const id = randomBytes(8).toString("hex");
  const keyFile = join(tmpdir(), `${id}.key`);
  const csrFile = join(tmpdir(), `${id}.csr`);
  const confFile = join(tmpdir(), `${id}.conf`);

  try {
    // Build OpenSSL config
    const sanList = [commonName, ...(sans as string[])].filter(Boolean);
    const sanStr = sanList.map((s, i) => `DNS.${i + 1} = ${s}`).join("\n");

    const conf = `[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = ${commonName}
${organization ? `O = ${organization}` : ""}
${organizationalUnit ? `OU = ${organizationalUnit}` : ""}
${locality ? `L = ${locality}` : ""}
${state ? `ST = ${state}` : ""}
C = ${country}
${email ? `emailAddress = ${email}` : ""}

[v3_req]
subjectAltName = @alt_names

[alt_names]
${sanStr}
`;

    await writeFile(confFile, conf);

    // Generate key
    let keyCmd: string;
    if (keyType === "EC") {
      keyCmd = `openssl ecparam -name ${curve} -genkey -noout -out "${keyFile}"`;
    } else {
      keyCmd = `openssl genrsa -out "${keyFile}" ${keySize}`;
    }
    await execAsync(keyCmd, { timeout: 30000 });

    // Generate CSR
    const csrCmd = `openssl req -new -${signatureAlgorithm} -key "${keyFile}" -out "${csrFile}" -config "${confFile}"`;
    await execAsync(csrCmd, { timeout: 30000 });

    const [privateKey, csr] = await Promise.all([readFile(keyFile, "utf-8"), readFile(csrFile, "utf-8")]);

    return NextResponse.json({ privateKey, csr });
  } catch (err: unknown) {
    const msg = err instanceof Error ? err.message : "CSR generation failed";
    return NextResponse.json({ error: msg }, { status: 200 });
  } finally {
    await Promise.allSettled([unlink(keyFile), unlink(csrFile), unlink(confFile)]);
  }
}
