/**
 * Message router for incoming gateway messages.
 *
 * Dispatches incoming messages to appropriate handlers based on message type.
 * Errors in handlers are caught and logged, never crashing the router.
 */
import { ErrorCode } from "@pocketcoder/shared/constants";
import { logger } from "../utils/logger.js";
import { isShutdownInProgress, trackInflight } from "../services/shutdown.js";
export class MessageRouter {
    handlers = new Map();
    client = null;
    /** Register a handler for a specific message type */
    registerHandler(type, handler) {
        this.handlers.set(type, handler);
    }
    /** Remove a handler for a specific message type */
    removeHandler(type) {
        this.handlers.delete(type);
    }
    /** Attach to a GatewayClient and start routing messages */
    attach(client) {
        this.client = client;
        client.on("message", this.handleMessage);
    }
    /** Detach from the current GatewayClient */
    detach() {
        if (this.client) {
            this.client.off("message", this.handleMessage);
            this.client = null;
        }
    }
    /** The bound message handler for the gateway client */
    handleMessage = (message) => {
        // Ignore ping messages (handled by GatewayClient itself)
        if (message.type === "ping") {
            return;
        }
        const msg = message;
        // Skip response and event messages — the daemon only handles requests
        if (msg.type.endsWith("_response") || msg.type === "error") {
            return;
        }
        // Reject new requests during shutdown
        if (isShutdownInProgress()) {
            if ("requestId" in msg && typeof msg.requestId === "string") {
                this.sendErrorResponse(msg.requestId, ErrorCode.DAEMON_BUSY, "Daemon is shutting down");
            }
            return;
        }
        const handler = this.handlers.get(msg.type);
        if (!handler) {
            logger.warn(`Unknown message type: ${msg.type}`);
            // Send error response if the message has a requestId
            if ("requestId" in msg && typeof msg.requestId === "string") {
                this.sendErrorResponse(msg.requestId, ErrorCode.INVALID_REQUEST, `Unknown message type: ${msg.type}`);
            }
            return;
        }
        const send = (response) => {
            if (this.client) {
                this.client.send(response);
            }
        };
        // Track in-flight request for graceful shutdown draining
        const release = trackInflight();
        // Execute handler, catching any errors
        handler(msg, send)
            .catch((err) => {
            const errorMessage = err instanceof Error ? err.message : String(err);
            logger.error(`Handler error for ${msg.type}: ${errorMessage}`);
            // Send error response if the message has a requestId
            if ("requestId" in msg && typeof msg.requestId === "string") {
                this.sendErrorResponse(msg.requestId, ErrorCode.UNKNOWN_ERROR, errorMessage);
            }
        })
            .finally(release);
    };
    /** Send a generic error response */
    sendErrorResponse(requestId, code, message) {
        if (!this.client)
            return;
        const errorResponse = {
            type: "error",
            requestId,
            error: { code, message },
        };
        this.client.send(errorResponse);
    }
}
//# sourceMappingURL=message-router.js.map