import { execFileSync } from "node:child_process";
import { copyFileSync, existsSync, readFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const scriptDir = dirname(fileURLToPath(import.meta.url));
const rootDir = resolve(scriptDir, "..");
const clientDir = join(rootDir, "node_modules", ".prisma", "client");
const clientIndex = join(clientDir, "index.js");
const prismaJs = join(rootDir, "node_modules", "prisma", "build", "index.js");
const genericEngine = join(clientDir, "libquery_engine.node");

function parseExpectedEngineFiles() {
  if (!existsSync(clientIndex)) return [];
  const content = readFileSync(clientIndex, "utf8");
  const matches = content.match(/libquery_engine-[^"'\\/]+?\.node/g) ?? [];
  return [...new Set(matches)];
}

function missingEngineFiles(expectedFiles) {
  return expectedFiles.filter((file) => !existsSync(join(clientDir, file)));
}

function runPrismaGenerate() {
  if (existsSync(prismaJs)) {
    execFileSync(process.execPath, [prismaJs, "generate"], {
      cwd: rootDir,
      stdio: "inherit",
      env: { ...process.env, PRISMA_HIDE_UPDATE_MESSAGE: "1" },
    });
    return;
  }

  throw new Error(
    "Prisma CLI not found at node_modules/prisma/build/index.js. Install dependencies and run `npm run prisma:generate`."
  );
}

let expectedFiles = parseExpectedEngineFiles();
let missingFiles = missingEngineFiles(expectedFiles);

if (!expectedFiles.length || missingFiles.length) {
  runPrismaGenerate();
  expectedFiles = parseExpectedEngineFiles();
  missingFiles = missingEngineFiles(expectedFiles);
}

if (missingFiles.length === 1 && existsSync(genericEngine)) {
  copyFileSync(genericEngine, join(clientDir, missingFiles[0]));
  missingFiles = missingEngineFiles(expectedFiles);
}

if (missingFiles.length) {
  throw new Error(
    `Missing Prisma engine file(s): ${missingFiles.join(
      ", "
    )}. Ensure deployment copies node_modules/.prisma (including dot-directories).`
  );
}
