/**
 * `/site-pages` route mount.
 *
 * - `GET /site-pages` with `?format=json` → index of all public site pages.
 * - `GET /site-pages/<route-slug>` with `?format=json` → single site page payload.
 *
 * Route-slug lookup matches by public route path (e.g. `/faq` is fetched via
 * `/site-pages/faq?format=json`). Nested routes use slashes (`primitives/entities`).
 *
 * This serves the same structural role as `/docs` but for public site pages
 * whose source of truth is canonical markdown in `docs/site/pages/<locale>/*.md`.
 *
 * Security:
 *   - Slug uses the same charset restriction as `/docs`.
 *   - Public read-only route; no auth required.
 *
 * Determinism: ordering is a pure function of (locale → nav_order → path).
 */
import path from "node:path";
import { fileURLToPath } from "node:url";
import { buildSitePageIndex, lookupSitePage, } from "./site_page_index_builder.js";
import fs from "node:fs";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
function resolveRepoRoot() {
    return path.resolve(__dirname, "..", "..", "..");
}
let sitePagesIndexCache = null;
const SLUG_RE = /^[A-Za-z0-9_./-]+$/;
function requestWantsJson(req) {
    if (req.query.format === "json")
        return true;
    const accept = String(req.headers.accept || "").toLowerCase();
    return accept.includes("application/json") || !accept;
}
function requestWantsHtml(acceptHeader) {
    if (!acceptHeader)
        return false;
    const value = acceptHeader.toLowerCase();
    return value.includes("text/html") || value.includes("application/xhtml+xml");
}
function getTreeMtimeMs(root) {
    let max = 0;
    const walk = (abs) => {
        let st;
        try {
            st = fs.statSync(abs);
        }
        catch {
            return;
        }
        max = Math.max(max, st.mtimeMs);
        if (!st.isDirectory())
            return;
        let entries;
        try {
            entries = fs.readdirSync(abs, { withFileTypes: true });
        }
        catch {
            return;
        }
        for (const ent of entries) {
            if (ent.name === "node_modules" || ent.name === ".git")
                continue;
            walk(path.join(abs, ent.name));
        }
    };
    walk(root);
    return max;
}
export function getSitePagesIndex(opts) {
    const repoRoot = opts.repoRoot ?? resolveRepoRoot();
    const sitePagesRoot = path.join(repoRoot, "docs", "site", "pages");
    const env = opts.envSource ?? process.env;
    const mtimeMs = getTreeMtimeMs(sitePagesRoot);
    const showInternal = env.NEOTOMA_DOCS_SHOW_INTERNAL === "true" ? "1" : "0";
    const key = `${sitePagesRoot}:${mtimeMs}:${showInternal}`;
    if (sitePagesIndexCache?.key === key)
        return sitePagesIndexCache.index;
    const index = buildSitePageIndex({ sitePagesRoot, env });
    sitePagesIndexCache = { key, index };
    return index;
}
export function mountSitePagesRoutes(app, opts = {}) {
    const repoRoot = opts.repoRoot ?? resolveRepoRoot();
    const sitePagesRoot = path.join(repoRoot, "docs", "site", "pages");
    app.get("/site-pages", (req, res, next) => {
        if (requestWantsHtml(req.headers.accept) && !requestWantsJson(req)) {
            return next();
        }
        const env = opts.envSource ?? process.env;
        const index = getSitePagesIndex({ repoRoot, envSource: env });
        const locale = req.query.locale;
        let filtered = index;
        if (locale === "en" || locale === "es") {
            const pages = index.pages.filter((p) => p.locale === locale);
            filtered = { pages, total: pages.length };
        }
        res.set("Content-Type", "application/json; charset=utf-8");
        res.set("Cache-Control", "public, max-age=60");
        res.status(200).json(filtered);
    });
    app.get("/site-pages/*", (req, res, next) => {
        if (requestWantsHtml(req.headers.accept) && !requestWantsJson(req)) {
            return next();
        }
        const rawSlug = req.params[0] ?? "";
        if (!rawSlug || rawSlug.includes("..") || !SLUG_RE.test(rawSlug)) {
            res.status(400).json({ error: "invalid_path", path: rawSlug });
            return;
        }
        const env = opts.envSource ?? process.env;
        const locale = req.query.locale || "en";
        const routePath = "/" + rawSlug;
        const page = lookupSitePage(routePath, { sitePagesRoot, env, locale });
        res.set("Content-Type", "application/json; charset=utf-8");
        res.set("Cache-Control", "public, max-age=60");
        if (!page) {
            res.status(404).json({ error: "site_page_not_found", path: routePath, locale });
            return;
        }
        res.status(200).json(page);
    });
}
//# sourceMappingURL=site_pages_route.js.map