import { ApiNotFoundError } from "@zuplo/errors";
import { editorConfig } from "../constants.js";
import { createEditorRoutes } from "./editor.js";
import { createFsRoutes } from "./fs.js";
import { createTestRoutes } from "./test.js";
const POLICIES_FILENAME = "policies.json";
export async function createApiRoutes(fastify, options) {
    const { sourceDirectory, logger, sseClients, deploymentUrl } = options;
    // Filesystem routes
    await fastify.register(createFsRoutes, {
        prefix: "/v1/deployments/:deploymentName/fs",
        sourceDirectory,
    });
    // Editor routes (for opening files in external editor)
    await fastify.register(createEditorRoutes, {
        prefix: "/v1/editor",
        sourceDirectory,
    });
    // Test routes (for proxying test requests to local Zuplo gateway)
    await fastify.register(createTestRoutes, {
        prefix: "/v1/test",
        logger,
    });
    // Server-Sent Events for file changes
    fastify.get("/changes", async (request, reply) => {
        // Hijack the reply to keep connection open
        reply.hijack();
        reply.raw.writeHead(200, {
            "Content-Type": "text/event-stream",
            "Cache-Control": "no-cache",
            Connection: "keep-alive",
        });
        // Flush headers immediately
        if (typeof reply.raw.flushHeaders === "function") {
            reply.raw.flushHeaders();
        }
        // Send initial event
        reply.raw.write(`data: ${JSON.stringify({ type: "init", filePath: POLICIES_FILENAME })}\n\n`);
        sseClients.add(reply.raw);
        // Send keep-alive comments to prevent proxy/browser timeouts
        const keepAliveInterval = setInterval(() => {
            try {
                if (reply.raw.writable) {
                    reply.raw.write(": keep-alive\n\n");
                }
                else {
                    clearInterval(keepAliveInterval);
                }
            }
            catch (err) {
                logger.debug(err, "Error sending SSE keep-alive");
                clearInterval(keepAliveInterval);
            }
        }, editorConfig.sse.keepAliveInterval);
        request.raw.on("close", () => {
            clearInterval(keepAliveInterval);
            sseClients.delete(reply.raw);
        });
        request.raw.on("error", (err) => {
            logger.debug(err, "SSE connection error");
            clearInterval(keepAliveInterval);
            sseClients.delete(reply.raw);
        });
    });
    // Health check
    fastify.get("/ping", async (_request, reply) => {
        reply.status(200).send();
    });
    // Get deployment info (includes URL for local gateway)
    fastify.get("/v1/deployments/:deploymentName", async (_request, reply) => {
        reply.status(200).send({
            deploymentVersion: {
                stages: [
                    {
                        stage: "api",
                        url: deploymentUrl,
                    },
                ],
            },
        });
    });
    // Return empty versions list for local mode (no build history)
    fastify.get("/v1/deployments/:deploymentName/versions", async (_request, reply) => {
        reply.status(200).send({ data: [] });
    });
    // Serve CDN content (schemas, etc) by proxying to the real Zuplo CDN
    // The frontend is configured with CDN_URL="/api" in local mode
    // So requests like /api/schemas/openapi-v3.1-zuplo.json need to be proxied
    fastify.get("/schemas/*", async (request, reply) => {
        // Remove /api prefix and fetch from CDN
        const cdnPath = request.url.replace("/api", "");
        const cdnUrl = `https://cdn.zuplo.com${cdnPath}`;
        const response = await fetch(cdnUrl);
        if (!response.ok) {
            throw new ApiNotFoundError();
        }
        const contentType = response.headers.get("content-type");
        if (contentType) {
            reply.header("Content-Type", contentType);
        }
        const data = await response.text();
        reply.send(data);
    });
}
//# sourceMappingURL=api.js.map