import { randomUUID } from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { hasOwnErrorCode } from "../error-codes.js";
import { TOOLCRAFT_LANDING_PAGE } from "../examples/toolcraft.js";
import { renderLandingPage } from "../render.js";
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const TEMP_WRITE_MAX_ATTEMPTS = 3;
export async function buildSite(options = {}) {
    const fileSystem = options.fs ?? fs;
    const outputDirectory = options.outputDirectory ?? path.join(packageRoot, "dist-site");
    const html = renderLandingPage(TOOLCRAFT_LANDING_PAGE);
    await fileSystem.mkdir(outputDirectory, { recursive: true });
    await Promise.all([
        writeFileAtomically(fileSystem, path.join(outputDirectory, "index.html"), html),
        writeFileAtomically(fileSystem, path.join(outputDirectory, ".nojekyll"), "")
    ]);
}
async function writeFileAtomically(fileSystem, filePath, contents) {
    for (let attempt = 1; attempt <= TEMP_WRITE_MAX_ATTEMPTS; attempt += 1) {
        const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
        try {
            await writeTempThenRename(fileSystem, tempPath, filePath, contents);
            return;
        }
        catch (error) {
            if (isExistingPath(error) && attempt < TEMP_WRITE_MAX_ATTEMPTS) {
                continue;
            }
            throw error;
        }
    }
}
async function writeTempThenRename(fileSystem, tempPath, filePath, contents) {
    let tempCreated = false;
    try {
        await fileSystem.writeFile(tempPath, contents, { encoding: "utf8", flag: "wx" });
        tempCreated = true;
        await fileSystem.rename(tempPath, filePath);
    }
    catch (error) {
        if (tempCreated || !isExistingPath(error)) {
            await fileSystem.rm(tempPath, { force: true }).catch(() => undefined);
        }
        throw error;
    }
}
function isExistingPath(error) {
    return hasOwnErrorCode(error, "EEXIST");
}
if (process.argv[1] !== undefined &&
    path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
    await buildSite();
}
