import { timingSafeEqual } from "node:crypto";
import { readConfiguration } from "./config.js";
import { WhatsAppWebSessionManager } from "./session-manager.js";
const configuration = readConfiguration();
const manager = new WhatsAppWebSessionManager({
    directory: configuration.sessionDirectory,
    encryptionKey: configuration.sessionEncryptionKey,
    callbackSecret: configuration.callbackSecret,
    logLevel: configuration.logLevel,
});
export const bridgeReady = manager.restore();
function json(response, status, body) {
    response.writeHead(status, {
        "Content-Type": "application/json; charset=utf-8",
        "Cache-Control": "no-store",
        "X-Content-Type-Options": "nosniff",
    });
    response.end(JSON.stringify(body));
}
function authorized(request) {
    const supplied = request.headers.authorization?.replace(/^Bearer\s+/i, "") ?? "";
    const expected = configuration.apiSecret;
    const left = Buffer.from(supplied);
    const right = Buffer.from(expected);
    return left.length === right.length && timingSafeEqual(left, right);
}
async function body(request) {
    const chunks = [];
    let size = 0;
    for await (const chunk of request) {
        const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
        size += bytes.length;
        if (size > 1_000_000)
            throw new Error("Request body is too large");
        chunks.push(bytes);
    }
    const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
        throw new Error("JSON body must be an object");
    }
    return parsed;
}
function validSessionId(value) {
    return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
}
export async function handleBridgeRequest(request, response) {
    try {
        await bridgeReady;
        const url = new URL(request.url ?? "/", `http://${request.headers.host ?? "localhost"}`);
        if (request.method === "GET" && url.pathname === "/health") {
            json(response, 200, { status: "ok", service: "bgm-whatsapp-web-bridge" });
            return;
        }
        if (!authorized(request)) {
            json(response, 401, { code: "UNAUTHORIZED" });
            return;
        }
        if (request.method === "POST" && url.pathname === "/v1/sessions") {
            const input = await body(request);
            const sessionId = String(input.sessionId ?? "");
            const callbackUrl = String(input.callbackUrl ?? "");
            if (!validSessionId(sessionId))
                throw new Error("sessionId is invalid");
            const callback = new URL(callbackUrl);
            if (callback.protocol !== "https:" && callback.hostname !== "localhost") {
                throw new Error("callbackUrl must use HTTPS");
            }
            json(response, 201, await manager.create(sessionId, callback.toString()));
            return;
        }
        const match = url.pathname.match(/^\/v1\/sessions\/([^/]+)(?:\/(messages|disconnect))?$/);
        if (!match || !validSessionId(match[1])) {
            json(response, 404, { code: "NOT_FOUND" });
            return;
        }
        if (request.method === "GET" && !match[2]) {
            json(response, 200, manager.read(match[1]));
            return;
        }
        if (request.method === "POST" && match[2] === "disconnect") {
            await body(request);
            json(response, 200, await manager.disconnect(match[1]));
            return;
        }
        if (request.method === "POST" && match[2] === "messages") {
            json(response, 201, await manager.send(match[1], await body(request)));
            return;
        }
        json(response, 405, { code: "METHOD_NOT_ALLOWED" });
    }
    catch (error) {
        json(response, 400, {
            code: "BRIDGE_REQUEST_FAILED",
            message: error instanceof Error ? error.message : "Bridge request failed",
        });
    }
}
