import { cp, mkdir, rm, stat, writeFile } from "node:fs/promises";
import { isAbsolute, relative, resolve, sep } from "node:path";
import { fileURLToPath } from "node:url";

function isWithin(parent, candidate) {
  const relationship = relative(parent, candidate);
  return relationship === ""
    || (!relationship.startsWith(`..${sep}`)
      && relationship !== ".."
      && !isAbsolute(relationship));
}

function pathsOverlap(left, right) {
  return isWithin(left, right) || isWithin(right, left);
}

export async function packagePages({ clientDirectory, serverDirectory, outputDirectory }) {
  const client = resolve(clientDirectory);
  const server = resolve(serverDirectory);
  const output = resolve(outputDirectory);
  const serverEntry = resolve(server, "index.js");
  if (!(await stat(serverEntry).catch(() => null))?.isFile()) {
    throw new Error("The vinext server entry is missing.");
  }
  if (pathsOverlap(client, output) || pathsOverlap(server, output)) {
    throw new Error("Pages output must not overlap a source directory.");
  }
  await rm(output, { recursive: true, force: true });
  await mkdir(output, { recursive: true });
  await cp(client, output, { recursive: true });
  const workerDirectory = resolve(output, "server");
  const workerEntry = resolve(output, "_worker.js");
  const routesFile = resolve(output, "_routes.json");
  await cp(server, workerDirectory, { recursive: true });
  await rm(resolve(workerDirectory, "wrangler.json"), { force: true });
  await writeFile(workerEntry, 'export { default } from "./server/index.js";\n', "utf8");
  await writeFile(
    routesFile,
    `${JSON.stringify({ version: 1, include: ["/*"], exclude: ["/_next/static/*"] }, null, 2)}\n`,
    "utf8",
  );
  return { workerEntry, routesFile };
}

const projectDirectory = fileURLToPath(new URL("../", import.meta.url));
const entryPath = process.argv[1] ? resolve(process.argv[1]) : "";
if (entryPath === fileURLToPath(import.meta.url)) {
  await packagePages({
    clientDirectory: resolve(projectDirectory, "dist", "client"),
    serverDirectory: resolve(projectDirectory, "dist", "server"),
    outputDirectory: resolve(projectDirectory, "dist", "pages"),
  });
  console.log("Packaged HearBooks for Cloudflare Pages Advanced Mode.");
}
