import { EventEmitter } from "node:events";
import { logger } from "../logger.js";
/**
 * TUI channel adapter for local terminal UI communication.
 *
 * Unlike Telegram/Gmail adapters that listen on external APIs, the TUI adapter
 * is purely in-process: inbound messages arrive via the TUI HTTP server
 * (POST /tui/send), and outbound replies are pushed to the SSE client
 * associated with the target sender ID.
 */
export class TuiAdapter extends EventEmitter {
    name = "tui";
    sseClients = new Map();
    eventBuffers = new Map();
    maxBufferSize = 200;
    start() {
        logger.channel("tui", "Adapter ready (waiting for TUI client connections)");
        return Promise.resolve();
    }
    stop() {
        for (const clients of this.sseClients.values()) {
            for (const res of clients) {
                try {
                    res.end();
                }
                catch { /* ignore */ }
            }
        }
        this.sseClients.clear();
        this.eventBuffers.clear();
        return Promise.resolve();
    }
    sendMessage(to, message, attachments, _replyTo) {
        const event = {
            type: "reply",
            timestamp: new Date().toISOString(),
            message,
            attachments,
        };
        this.pushEvent(event, to);
        return Promise.resolve();
    }
    addSseClient(res, senderId) {
        res.writeHead(200, {
            "content-type": "text/event-stream; charset=utf-8",
            "cache-control": "no-store",
            "connection": "keep-alive",
            "x-content-type-options": "nosniff",
        });
        res.write(`: connected\n\n`);
        const buffer = this.eventBuffers.get(senderId);
        if (buffer) {
            for (const event of buffer) {
                res.write(`data: ${JSON.stringify(event)}\n\n`);
            }
        }
        let clientSet = this.sseClients.get(senderId);
        if (!clientSet) {
            clientSet = new Set();
            this.sseClients.set(senderId, clientSet);
        }
        clientSet.add(res);
        const heartbeat = setInterval(() => {
            try {
                res.write(`: ping\n\n`);
            }
            catch { /* ignore */ }
        }, 10_000);
        const capturedSet = clientSet;
        res.on("close", () => {
            clearInterval(heartbeat);
            capturedSet.delete(res);
            if (capturedSet.size === 0) {
                this.sseClients.delete(senderId);
            }
        });
    }
    get connectedClients() {
        let count = 0;
        for (const clients of this.sseClients.values()) {
            count += clients.size;
        }
        return count;
    }
    pushEvent(event, senderId) {
        if (senderId) {
            let buffer = this.eventBuffers.get(senderId);
            if (!buffer) {
                buffer = [];
                this.eventBuffers.set(senderId, buffer);
            }
            buffer.push(event);
            if (buffer.length > this.maxBufferSize)
                buffer.shift();
            const clients = this.sseClients.get(senderId);
            if (clients) {
                const data = `data: ${JSON.stringify(event)}\n\n`;
                for (const client of clients) {
                    try {
                        client.write(data);
                    }
                    catch { /* ignore */ }
                }
            }
        }
        else {
            const data = `data: ${JSON.stringify(event)}\n\n`;
            for (const [sid, clients] of this.sseClients) {
                let buffer = this.eventBuffers.get(sid);
                if (!buffer) {
                    buffer = [];
                    this.eventBuffers.set(sid, buffer);
                }
                buffer.push(event);
                if (buffer.length > this.maxBufferSize)
                    buffer.shift();
                for (const client of clients) {
                    try {
                        client.write(data);
                    }
                    catch { /* ignore */ }
                }
            }
        }
    }
    injectMessage(msg) {
        this.emit("message", msg);
    }
}
//# sourceMappingURL=tui.js.map