"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = startServer;
const sqlite_1 = require("@aigne/sqlite");
const chalk_1 = __importDefault(require("chalk"));
const cookie_parser_1 = __importDefault(require("cookie-parser"));
const cors_1 = __importDefault(require("cors"));
const dotenv_flow_1 = __importDefault(require("dotenv-flow"));
const express_1 = __importDefault(require("express"));
const express_sse_1 = __importDefault(require("express-sse"));
const terminal_link_1 = __importDefault(require("terminal-link"));
const zod_1 = require("zod");
const migrate_js_1 = require("./migrate.js");
const settings_js_1 = __importDefault(require("./routes/settings.js"));
const trace_js_1 = __importDefault(require("./routes/trace.js"));
const sse = new express_sse_1.default();
dotenv_flow_1.default.config({ silent: true });
const expressMiddlewareSchema = zod_1.z.custom();
function formatFn(schema) {
    return zod_1.z
        .function()
        .args(zod_1.z.array(schema))
        .returns(zod_1.z.promise(zod_1.z.array(schema)))
        .optional();
}
const startServerOptionsSchema = zod_1.z.object({
    port: zod_1.z.number().int().positive(),
    dbUrl: zod_1.z.string().min(1),
    traceTreeMiddleware: zod_1.z.array(expressMiddlewareSchema).optional(),
    options: zod_1.z
        .object({
        formatOutputFiles: formatFn(zod_1.z.object({
            mimeType: zod_1.z.string(),
            type: zod_1.z.string(),
            data: zod_1.z.string(),
        })),
        formatOutputImages: formatFn(zod_1.z.object({
            base64: zod_1.z.string(),
        })),
    })
        .optional(),
});
const MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || "30 mb";
async function startServer(options) {
    const { port, dbUrl } = startServerOptionsSchema.parse(options);
    const middleware = options.traceTreeMiddleware ?? [
        (_req, _res, next) => next(),
    ];
    const db = await (0, sqlite_1.initDatabase)({ url: dbUrl });
    await (0, migrate_js_1.migrate)(db);
    const app = (0, express_1.default)();
    app.locals.db = db;
    app.set("trust proxy", true);
    // @ts-ignore
    app.use((0, cookie_parser_1.default)());
    app.use(express_1.default.json({ limit: MAX_REQUEST_BODY_SIZE }));
    app.use(express_1.default.urlencoded({ extended: true, limit: MAX_REQUEST_BODY_SIZE }));
    app.use((0, cors_1.default)());
    app.get("/api/sse", sse.init);
    app.use("/api/trace", (0, trace_js_1.default)({
        options: options.options,
        sse,
        middleware: Array.isArray(middleware) ? middleware : [middleware],
    }));
    app.use("/api/settings", (0, settings_js_1.default)({
        middleware: Array.isArray(middleware) ? middleware : [middleware],
    }));
    app.get("/health", (_req, res) => {
        res.send("ok");
    });
    app.use((err, _req, res, _next) => {
        if (err instanceof zod_1.ZodError) {
            res.status(400).json({ success: false, error: err.message });
        }
        else {
            const message = err instanceof Error ? err.message : "Unknown error";
            res.status(500).json({ success: false, error: message });
        }
    });
    const server = app.listen(Number(port), () => {
        const url = `http://localhost:${port}`;
        const renderedMessage = (message) => `Running observability server on ${message}`;
        const message = terminal_link_1.default.isSupported
            ? (0, terminal_link_1.default)(chalk_1.default.greenBright(url), url)
            : chalk_1.default.greenBright(url);
        const msg = renderedMessage(message);
        console.log(msg);
    });
    return { app, server };
}
