/**
 * TelegramChannel — MessagingChannelPort adapter for Telegram Bot API.
 *
 * Uses native fetch (Node 18+). MarkdownV2 escaping applied automatically.
 * No axios or other HTTP packages.
 *
 * @public
 */
import { InvalidTargetError } from "../../ports/messaging.js";
/** Emoji prefix per alert level. */
const LEVEL_EMOJI = {
    info: "ℹ️",
    warn: "⚠️",
    error: "❌",
    critical: "🚨",
};
/**
 * Escape text for Telegram MarkdownV2.
 * https://core.telegram.org/bots/api#markdownv2-style
 */
function escapeMdV2(text) {
    // Characters that must be escaped in MarkdownV2
    return text.replace(/[_*[\]()~`>#+\-=|{}.!\\]/g, (ch) => `\\${ch}`);
}
/** Rate-limit error code from Telegram API. */
const TELEGRAM_RATE_LIMIT_CODE = 429;
/**
 * Thrown when Telegram returns a 429 Too Many Requests.
 *
 * @public
 */
export class TelegramRateLimitError extends Error {
    retryAfterSeconds;
    constructor(retryAfterSeconds) {
        super(`Telegram rate limit hit${retryAfterSeconds != null ? `; retry after ${retryAfterSeconds}s` : ""}`);
        this.retryAfterSeconds = retryAfterSeconds;
        this.name = "TelegramRateLimitError";
        Object.setPrototypeOf(this, new.target.prototype);
    }
}
export class TelegramChannel {
    #botToken;
    #defaultChatId;
    constructor(config) {
        this.#botToken = config.botToken;
        this.#defaultChatId = config.defaultChatId;
    }
    async sendAlert(level, title, body) {
        const chatId = this.#defaultChatId;
        if (!chatId) {
            throw new InvalidTargetError("TelegramChannel.sendAlert requires defaultChatId in constructor config", "");
        }
        const emoji = LEVEL_EMOJI[level];
        const levelUpper = level.toUpperCase();
        const text = `${emoji} *\\[${escapeMdV2(levelUpper)}\\] ${escapeMdV2(title)}*\n` +
            `${escapeMdV2(body)}`;
        await this.#post(chatId, text, "MarkdownV2");
    }
    async sendMessage(target, text) {
        if (!target || target.trim() === "") {
            throw new InvalidTargetError("TelegramChannel.sendMessage requires a non-empty target (chat_id or @channel)", target);
        }
        await this.#post(target.trim(), text);
    }
    async #post(chatId, text, parseMode) {
        const url = `https://api.telegram.org/bot${this.#botToken}/sendMessage`;
        const body = { chat_id: chatId, text };
        if (parseMode)
            body["parse_mode"] = parseMode;
        const res = await fetch(url, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(body),
        });
        if (res.status === TELEGRAM_RATE_LIMIT_CODE) {
            const data = (await res.json().catch(() => ({})));
            throw new TelegramRateLimitError(data.parameters?.retry_after);
        }
        if (!res.ok) {
            const data = (await res.json().catch(() => ({})));
            throw new Error(`Telegram API error ${res.status}: ${data.description ?? "unknown"}`);
        }
    }
}
//# sourceMappingURL=telegram.js.map