import * as path from "node:path";
import { renderGateReportFragment } from "./gate-report-fragment.js";
import { buildGateReport } from "./gate-report.js";
const JSON_CONTENT_TYPE = "application/json; charset=utf-8";
const NO_STORE = "no-store";
const TEXT_CONTENT_TYPE = "text/plain; charset=utf-8";
/**
 * Build the response for one project.
 * @param projectRoot - Project root served by this UI process
 * @param dependencies - Injectable boundaries
 * @returns The fragment and the payload it came from
 */
export async function readGateReport(projectRoot, dependencies = {}) {
    const build = dependencies.build ??
        (async (root) => await buildGateReport({ projectRoot: root }));
    const report = await build(projectRoot);
    return {
        report,
        html: renderGateReportFragment(report, path.basename(projectRoot)),
    };
}
/**
 * Coalesce concurrent reads without caching a stale answer for later ones.
 *
 * The slot is a `current` holder rather than a reassigned binding, which is
 * the shape the repository's immutability rules already sanction: the entry is
 * set when a read starts and cleared when it settles, which is the same
 * lifetime with none of the suppression.
 * @param read - The underlying reader
 * @returns A single-flight reader that clears after settlement
 */
function singleFlight(read) {
    const slot = {
        current: undefined,
    };
    return () => {
        if (slot.current !== undefined)
            return slot.current;
        const pending = read();
        slot.current = pending;
        const clear = () => {
            if (slot.current === pending)
                slot.current = undefined;
        };
        void pending.then(clear, clear);
        return pending;
    };
}
/**
 * Create the `/api/gate-report` handler for one project.
 * @param projectRoot - Project root served by this UI process
 * @param dependencies - Injectable boundaries
 * @returns A request handler
 */
export function createGateReportHandler(projectRoot, dependencies = {}) {
    const read = singleFlight(async () => await readGateReport(projectRoot, dependencies));
    return (request, response) => {
        if (request.method === "HEAD") {
            response.writeHead(200, {
                "cache-control": NO_STORE,
                "content-type": JSON_CONTENT_TYPE,
            });
            response.end();
            return;
        }
        if (request.method !== "GET") {
            response.writeHead(405, {
                allow: "GET, HEAD",
                "cache-control": NO_STORE,
                "content-type": TEXT_CONTENT_TYPE,
            });
            response.end("Method not allowed");
            return;
        }
        void read().then(result => {
            response.writeHead(200, {
                "cache-control": NO_STORE,
                "content-type": JSON_CONTENT_TYPE,
            });
            response.end(JSON.stringify(result));
        }, error => {
            // A failure here must not render as an empty report. The console shows
            // the message, which keeps "the report could not be derived" distinct
            // from "the report found nothing".
            response.writeHead(500, {
                "cache-control": NO_STORE,
                "content-type": JSON_CONTENT_TYPE,
            });
            response.end(JSON.stringify({
                error: error instanceof Error ? error.message : String(error),
            }));
        });
    };
}
//# sourceMappingURL=ui-gate-report.js.map