import { randomUUID } from "node:crypto";
import { cpSync, existsSync, readFileSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import dotenv from "dotenv";
import { logger } from "../common/logger.js";
import { ConsoleOutput, printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, } from "../common/output.js";
import { isPortAvailable } from "../common/utils/ports.js";
import { handleRuntimeStdio } from "../common/worker-output.js";
import { ApiServer } from "../editor/server/server.js";
export async function dev(argv) {
    const sourceDirectory = resolve(join(relative(process.cwd(), argv.dir)));
    const zuploRuntimePath = new URL("../../node_modules/@zuplo/runtime", import.meta.url);
    if (existsSync(zuploRuntimePath)) {
        cpSync(zuploRuntimePath, join(sourceDirectory, "node_modules/@zuplo/runtime"), {
            recursive: true,
            dereference: true,
        });
    }
    process.env.GLOBAL_MODULE_LOCATION = fileURLToPath(new URL("../../node_modules", import.meta.url));
    const loadedEnvFiles = [];
    const envFile = join(sourceDirectory, ".env");
    if (existsSync(envFile)) {
        loadedEnvFiles.push(".env");
    }
    let envZuplo;
    const envZuploFile = join(sourceDirectory, ".env.zuplo");
    if (existsSync(envZuploFile)) {
        const contents = readFileSync(envZuploFile);
        envZuplo = dotenv.parse(contents);
        loadedEnvFiles.push(".env.zuplo");
    }
    process.env.ZUPLO_IS_LOCAL_DEVELOPMENT = "true";
    const core = await import("@zuplo/core/cli");
    const zupPort = argv.port;
    const zupEditorPort = argv.editorPort;
    const zupDebugPort = argv.debugPort;
    const isZupPortAvailable = await isPortAvailable("localhost", zupPort);
    if (!isZupPortAvailable) {
        await printCriticalFailureToConsoleAndExit(`Port ${zupPort} is already in use. Please specify a different port using --port.`);
    }
    const isZupEditorPortAvailable = await isPortAvailable("localhost", zupEditorPort);
    if (!isZupEditorPortAvailable) {
        await printCriticalFailureToConsoleAndExit(`Port ${zupEditorPort} is already in use. Please specify a different port using --editor-port.`);
    }
    if (zupDebugPort) {
        const isZupDebugPortAvailable = await isPortAvailable("localhost", zupDebugPort);
        if (!isZupDebugPortAvailable) {
            await printCriticalFailureToConsoleAndExit(`Port ${zupDebugPort} is already in use. Please specify a different port using --debug-port.`);
        }
    }
    const buildId = randomUUID();
    let firstLoad = true;
    await core.startDevServer({
        buildId,
        output: new ConsoleOutput(),
        sourceDirectory,
        port: zupPort,
        debugPort: argv.debugPort ?? undefined,
        publicZuploEnvironmentVariables: envZuplo
            ? {
                ZUPLO_ACCOUNT_NAME: envZuplo.ZUPLO_ACCOUNT_NAME,
                ZUPLO_PROJECT_NAME: envZuplo.ZUPLO_PROJECT_NAME,
                ZUPLO_ENVIRONMENT_TYPE: envZuplo.ZUPLO_ENVIRONMENT_TYPE,
            }
            :
                undefined,
        logger,
        handleRuntimeStdio,
        onReload: () => {
            if (firstLoad) {
                firstLoad = false;
            }
            else {
                printDiagnosticsToConsole("Code changed. Server reloaded...");
            }
        },
    });
    let editor;
    if (argv["start-editor"]) {
        editor = new ApiServer({
            cliArgs: argv,
            workingDir: sourceDirectory,
            port: argv.editorPort,
            isStandalone: false,
        });
        editor.start().catch((err) => logger.error(err));
    }
    printDiagnosticsToConsole("Started local development setup");
    printDiagnosticsToConsole("Ctrl+C to exit");
    printDiagnosticsToConsole("");
    printDiagnosticsToConsole(`🚀 Zuplo Gateway: http://localhost:${zupPort}`);
    if (argv["start-editor"]) {
        printDiagnosticsToConsole(`📘 Route Designer: http://localhost:${argv.editorPort}`);
    }
    if (loadedEnvFiles.length > 0) {
        printDiagnosticsToConsole(`⚙️  Loaded env files: \n    - ${loadedEnvFiles.join(" \n    - ")}`);
    }
    printDiagnosticsToConsole("");
    printDiagnosticsToConsole("");
    return new Promise((resolve) => {
        async function exit() {
            printDiagnosticsToConsole("");
            printDiagnosticsToConsole("Stopping local development server...");
            if (argv["start-editor"]) {
                await editor.close();
            }
            resolve();
        }
        process.on("SIGTERM", exit);
        process.on("SIGINT", exit);
    });
}
//# sourceMappingURL=handler.js.map