import express from "express";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { actorMiddleware } from "../middleware/auth.js";
import { errorHandler, httpLogger } from "../middleware/index.js";
import { privateHostnameGuard, resolvePrivateHostnameAllowSet } from "../middleware/private-hostname-guard.js";
import { llmRoutes } from "../routes/llms.js";
import { pluginUiStaticRoutes } from "../routes/plugin-ui-static.js";
import { DEFAULT_LOCAL_PLUGIN_DIR } from "../services/plugin-loader.js";
import { applyUiBranding } from "../ui-branding.js";
import { registerApiRoutes } from "./register-api-routes.js";
export function resolveViteHmrPort(serverPort) {
    if (serverPort <= 55_535) {
        return serverPort + 10_000;
    }
    return Math.max(1_024, serverPort - 10_000);
}
export async function createHttpApp(db, opts, pluginRuntime) {
    const app = express();
    const privateHostnameGateEnabled = opts.deploymentMode === "authenticated" && opts.deploymentExposure === "private";
    const privateHostnameAllowSet = resolvePrivateHostnameAllowSet({
        allowedHostnames: opts.allowedHostnames,
        bindHost: opts.bindHost,
    });
    app.use(express.json({
        // Organization import/export payloads can inline full portable packages.
        limit: "10mb",
        verify: (req, _res, buf) => {
            req.rawBody = buf;
        },
    }));
    app.use(httpLogger);
    app.use(privateHostnameGuard({
        enabled: privateHostnameGateEnabled,
        allowedHostnames: opts.allowedHostnames,
        bindHost: opts.bindHost,
    }));
    app.use(actorMiddleware(db, {
        deploymentMode: opts.deploymentMode,
        resolveSession: opts.resolveSession,
    }));
    app.get("/api/auth/get-session", (req, res) => {
        if (req.actor.type !== "board" || !req.actor.userId) {
            res.status(401).json({ error: "Unauthorized" });
            return;
        }
        res.json({
            session: {
                id: `rudder:${req.actor.source}:${req.actor.userId}`,
                userId: req.actor.userId,
            },
            user: {
                id: req.actor.userId,
                email: null,
                name: req.actor.source === "local_implicit" ? "Local Board" : null,
            },
        });
    });
    if (opts.betterAuthHandler) {
        app.all("/api/auth/*authPath", opts.betterAuthHandler);
    }
    app.use(llmRoutes(db));
    app.use("/api", registerApiRoutes(db, opts, pluginRuntime));
    app.use("/api", (_req, res) => {
        res.status(404).json({ error: "API route not found" });
    });
    app.use(pluginUiStaticRoutes(db, {
        localPluginDir: opts.localPluginDir ?? DEFAULT_LOCAL_PLUGIN_DIR,
    }));
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    if (opts.uiMode === "static") {
        const candidates = [
            path.resolve(__dirname, "../../ui-dist"),
            path.resolve(__dirname, "../../../ui/dist"),
        ];
        const uiDist = candidates.find((candidate) => fs.existsSync(path.join(candidate, "index.html")));
        if (uiDist) {
            const indexHtml = applyUiBranding(fs.readFileSync(path.join(uiDist, "index.html"), "utf-8"));
            app.use(express.static(uiDist));
            app.get(/.*/, (_req, res) => {
                res.status(200).set("Content-Type", "text/html").end(indexHtml);
            });
        }
        else {
            console.warn("[rudder] UI dist not found; running in API-only mode");
        }
    }
    if (opts.uiMode === "vite-dev") {
        const uiRoot = path.resolve(__dirname, "../../../ui");
        const hmrPort = resolveViteHmrPort(opts.serverPort);
        const { createServer: createViteServer } = await import("vite");
        const vite = await createViteServer({
            root: uiRoot,
            appType: "custom",
            server: {
                middlewareMode: true,
                hmr: {
                    host: opts.bindHost,
                    port: hmrPort,
                    clientPort: hmrPort,
                },
                allowedHosts: privateHostnameGateEnabled ? Array.from(privateHostnameAllowSet) : undefined,
            },
        });
        app.use(vite.middlewares);
        app.get(/.*/, async (req, res, next) => {
            try {
                const templatePath = path.resolve(uiRoot, "index.html");
                const template = fs.readFileSync(templatePath, "utf-8");
                const html = applyUiBranding(await vite.transformIndexHtml(req.originalUrl, template));
                res.status(200).set({ "Content-Type": "text/html" }).end(html);
            }
            catch (err) {
                next(err);
            }
        });
    }
    app.use(errorHandler);
    return app;
}
//# sourceMappingURL=create-http-app.js.map