import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * @copyright Sister Software
 * @license AGPL-3.0
 * @author Teffen Ellis, et al.
 */
import { Spinner, StatusMessage } from "@inkjs/ui";
import express from "express";
import { Box, Text } from "ink";
import { repoRootPathBuilder } from "mailwoman/sdk/repo";
import { AddressRouter } from "mailwoman/server";
import cluster from "node:cluster";
import { availableParallelism } from "node:os";
import * as process from "node:process";
import { useEffect, useState } from "react";
import zod from "zod";
const ClusterManager = ({ options: { cpus = availableParallelism() }, }) => {
    const [workers, setWorkers] = useState();
    useEffect(() => {
        setWorkers(Array.from({ length: cpus }, () => cluster.fork()));
        cluster.on("exit", (worker, code, signal) => {
            console.log(`[${signal}] (${code}) Worker ${worker.process.pid} exited`);
        });
    }, [cpus]);
    if (!workers) {
        return _jsx(Text, { children: "Starting workers..." });
    }
    return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["Manager process: ", process.pid] }), _jsx(Text, { children: "Workers:" }), workers.map((worker) => (_jsx(WorkerStatus, { worker: worker }, worker.id)))] }));
};
const WorkerStatus = ({ worker }) => {
    const [status, setStatus] = useState("pending");
    const [message, setMessage] = useState();
    useEffect(() => {
        const onOnline = () => setStatus("online");
        const onExit = () => setStatus("exited");
        const onError = () => setStatus("error");
        const onListening = () => setStatus("listening");
        worker.on("online", onOnline);
        worker.on("exit", onExit);
        worker.on("error", onError);
        worker.on("listening", onListening);
        worker.on("message", (msg) => {
            setMessage(JSON.stringify(msg));
        });
        return () => {
            worker.off("online", onOnline);
            worker.off("exit", onExit);
            worker.off("error", onError);
            worker.off("listening", onListening);
        };
    }, [worker]);
    if (status === "pending") {
        return _jsx(Spinner, { label: "Starting worker..." });
    }
    if (status === "online") {
        return _jsxs(StatusMessage, { variant: "success", children: ["Online (", worker.process.pid, ")"] });
    }
    if (status === "exited") {
        return _jsxs(StatusMessage, { variant: "error", children: ["Exited (", worker.process.pid, ")"] });
    }
    if (status === "error") {
        return _jsxs(StatusMessage, { variant: "error", children: ["Error (", worker.process.pid, ")"] });
    }
    if (status === "listening") {
        return (_jsxs(StatusMessage, { variant: "info", children: ["Listening (", worker.process.pid, ") ", message] }));
    }
    return (_jsxs(StatusMessage, { variant: "error", children: ["Unknown status \"", status, "\" (", worker.process.pid, ")"] }));
};
const ChildThread = ({ options: { port, host } }) => {
    useEffect(() => {
        const app = express();
        app.use(express.json());
        app.use(AddressRouter);
        app.use("/admin/wof");
        const staticPath = repoRootPathBuilder("server", "static").toString();
        console.log("Serving static files from", staticPath);
        app.use(express.static(staticPath));
        app.listen(port, host, () => {
            cluster.worker?.send("HTTP server ready");
        });
    }, [host, port]);
    return null;
};
const ServerConfigSchema = zod.object({
    port: zod.number().optional().default(3000).describe("The port to listen on"),
    host: zod.string().optional().default("0.0.0.0").describe("The network interface to bind to"),
    cpus: zod.number().optional().describe("The number of CPUs to use"),
});
export const options = ServerConfigSchema;
const ParseCommand = cluster.isPrimary ? ClusterManager : ChildThread;
export default ParseCommand;
//# sourceMappingURL=serve.js.map