"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatToTelegramHTML = formatToTelegramHTML;
exports.startTelegramBot = startTelegramBot;
const telegraf_1 = require("telegraf");
const reasoning_1 = require("../agent/reasoning");
const parser_1 = require("../config/parser");
const transactionManager_1 = require("../agent/transactionManager");
const transfer_1 = require("../web3/skills/transfer");
const swapToken_1 = require("../web3/skills/swapToken");
const bridgeToken_1 = require("../web3/skills/bridgeToken");
const mintNft_1 = require("../web3/skills/mintNft");
const customTx_1 = require("../web3/skills/customTx");
const formatter_1 = require("../utils/formatter");
const picocolors_1 = __importDefault(require("picocolors"));
function formatToTelegramHTML(text) {
    if (!text)
        return "";
    let html = text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
    html = html.replace(/\*\*(.*?)\*\*/g, '<b>$1</b>');
    // Match italic * avoiding bullet points at the start of a line
    html = html.replace(/(?<!^|\n)\*(?!\s)(.*?)(?<!\s)\*/g, '<i>$1</i>');
    html = html.replace(/_(.*?)_/g, '<i>$1</i>');
    // Convert code blocks and inline code
    html = html.replace(/```([\s\S]*?)```/g, '<pre><code>$1</code></pre>');
    html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
    // Transform Markdown Tables to <pre> monospaced blocks so they don't break on mobile
    const tableRegex = /(?:\|.*\|(?:\n|$))+/g;
    html = html.replace(tableRegex, (match) => {
        return `<pre>${match.trim()}</pre>\n`;
    });
    return html;
}
function startTelegramBot() {
    const config = (0, parser_1.loadConfig)();
    const token = config.integrations?.telegram?.bot_token;
    if (!token) {
        console.log('[Telegram] No TELEGRAM_BOT_TOKEN found in config.yaml. Bot is disabled.');
        return;
    }
    try {
        const bot = new telegraf_1.Telegraf(token);
        // Pairing state variables
        const isPaired = !!config.integrations?.telegram?.authorized_chat_id;
        let generatedPin = '';
        let pinExpiry = 0;
        if (!isPaired) {
            generatedPin = Math.floor(100000 + Math.random() * 900000).toString();
            pinExpiry = Date.now() + 5 * 60 * 1000; // 5 minutes TTL
            console.log(picocolors_1.default.yellow('\n==================================================='));
            console.log(picocolors_1.default.yellow('🔐 OTORISASI BOT TELEGRAM DIBUTUHKAN'));
            console.log(picocolors_1.default.yellow('==================================================='));
            console.log('Bot Telegram Anda saat ini terkunci demi keamanan.');
            console.log('Buka Telegram Anda, dan kirimkan perintah berikut ke bot Anda:\n');
            console.log(picocolors_1.default.cyan(`  /auth ${generatedPin}\n`));
            console.log(picocolors_1.default.gray('(Kode OTP ini akan kedaluwarsa dalam 5 menit)\n'));
            console.log('⏳ Menunggu pesan masuk...');
        }
        // Security Middleware (OTP & Authorization)
        bot.use(async (ctx, next) => {
            const currentConfig = (0, parser_1.loadConfig)();
            const authId = currentConfig.integrations?.telegram?.authorized_chat_id;
            if (authId) {
                // Paired mode: Reject unauthorized users silently
                if (ctx.chat?.id !== authId) {
                    return;
                }
                return next();
            }
            // Pairing mode: Listen for /auth command
            if (ctx.message && 'text' in ctx.message) {
                const text = ctx.message.text || '';
                if (text.startsWith('/auth ')) {
                    const pin = text.split(' ')[1];
                    if (Date.now() > pinExpiry) {
                        await ctx.reply('❌ The pairing PIN has expired. Please restart the CLI to generate a new one.');
                        return;
                    }
                    if (pin === generatedPin) {
                        // Success
                        if (!currentConfig.integrations)
                            currentConfig.integrations = {};
                        if (!currentConfig.integrations.telegram)
                            currentConfig.integrations.telegram = { enabled: true, bot_token: token };
                        currentConfig.integrations.telegram.authorized_chat_id = ctx.chat?.id;
                        (0, parser_1.saveConfig)(currentConfig);
                        await ctx.reply('✅ Otorisasi Berhasil! Agen Nyxora kini hanya akan mematuhi perintah Anda. Koneksi diamankan.');
                        console.log(picocolors_1.default.green(`\n[Telegram] Successfully paired with Chat ID: ${ctx.chat?.id}`));
                        return; // Done parsing auth, ignore this specific message for further logic
                    }
                    else {
                        await ctx.reply('❌ PIN salah.');
                        return;
                    }
                }
            }
            // If not paired and not an auth command, silently drop
            return;
        });
        bot.command('clear', async (ctx) => {
            reasoning_1.logger.clear();
            await ctx.reply('✅ Memori AI telah dihapus. Mari kita mulai obrolan baru!');
        });
        bot.on('text', async (ctx) => {
            const text = ctx.message.text;
            if (text.startsWith('/'))
                return; // Ignore other commands
            console.log(`[Telegram] Received from ${ctx.from?.first_name || 'User'}: ${text}`);
            // Send typing action
            await ctx.sendChatAction('typing');
            try {
                let progressMsgId = null;
                const onProgress = async (progressText) => {
                    try {
                        if (!progressMsgId) {
                            const sent = await ctx.reply(`<i>${progressText.replace(/_/g, '')}</i>`, { parse_mode: 'HTML' });
                            progressMsgId = sent.message_id;
                        }
                        else {
                            await ctx.telegram.editMessageText(ctx.chat.id, progressMsgId, undefined, `<i>${progressText.replace(/_/g, '')}</i>`, { parse_mode: 'HTML' });
                        }
                    }
                    catch (e) { }
                };
                const response = await (0, reasoning_1.processUserInput)(text, 'user', onProgress);
                if (progressMsgId) {
                    await ctx.telegram.deleteMessage(ctx.chat.id, progressMsgId).catch(() => { });
                }
                const pendingTxs = transactionManager_1.txManager.getPending();
                if (pendingTxs.length > 0) {
                    const latestTx = pendingTxs[pendingTxs.length - 1];
                    if (Date.now() - latestTx.createdAt < 120000) {
                        await ctx.reply(formatToTelegramHTML(response), {
                            parse_mode: 'HTML',
                            ...telegraf_1.Markup.inlineKeyboard([
                                [
                                    telegraf_1.Markup.button.callback('✅ Approve', `approve_${latestTx.id}`),
                                    telegraf_1.Markup.button.callback('❌ Reject', `reject_${latestTx.id}`)
                                ]
                            ])
                        });
                        return;
                    }
                }
                await ctx.reply(formatToTelegramHTML(response), { parse_mode: 'HTML' });
            }
            catch (error) {
                console.error('[Telegram] Error processing message:', error);
                await ctx.reply('❌ Sorry, I encountered an error while processing your message.');
            }
        });
        // Handle callbacks
        bot.action(/^approve_(.+)$/, async (ctx) => {
            const txId = ctx.match[1];
            const tx = transactionManager_1.txManager.getTransaction(txId);
            if (!tx || tx.status !== 'pending') {
                await ctx.answerCbQuery('Transaction not found or already processed.', { show_alert: true });
                return;
            }
            await ctx.answerCbQuery('Processing transaction...');
            await ctx.reply(`⏳ Processing transaction ${txId}...`);
            // Remove inline keyboard immediately
            await ctx.editMessageReplyMarkup(undefined).catch(() => { });
            try {
                let result = '';
                if (tx.type === 'transfer') {
                    result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details);
                }
                else if (tx.type === 'swap') {
                    result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details);
                }
                else if (tx.type === 'bridge') {
                    result = await (0, bridgeToken_1.executeBridge)(tx.chainName, tx.details);
                }
                else if (tx.type === 'mint') {
                    result = await (0, mintNft_1.executeMintNft)(tx.chainName, tx.details);
                }
                else if (tx.type === 'custom') {
                    result = await (0, customTx_1.executeCustomTx)(tx.chainName, tx.details);
                }
                transactionManager_1.txManager.updateStatus(txId, 'executed', result);
                // Pass session history to formatTransactionSuccess to detect language
                const sessionId = ctx.chat?.id.toString() || 'default';
                const history = reasoning_1.logger.getHistory(sessionId);
                let isIndonesian = false;
                if (history.length > 0) {
                    const lastMsg = history[history.length - 1].content.toLowerCase();
                    const idWords = ['saya', 'kamu', 'aku', 'apa', 'bagaimana', 'kenapa', 'bisa', 'tolong', 'ke', 'di', 'dari', 'yang', 'ini', 'itu', 'buat', 'cek', 'saldo'];
                    if (idWords.some(w => lastMsg.includes(w)))
                        isIndonesian = true;
                }
                const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result, isIndonesian);
                await ctx.reply(formatToTelegramHTML(`✅ **Transaction processed:**\n\n${prettyMsg}`), { parse_mode: 'HTML' });
                reasoning_1.logger.addEntry({ role: 'assistant', content: `✅ Transaction processed:\n\n${prettyMsg}` });
                reasoning_1.logger.addEntry({ role: 'tool', name: tx.type === 'swap' ? 'swap_token' : 'transfer_native', content: result });
                (0, reasoning_1.processUserInput)(`Transaction ${txId} was APPROVED via Telegram. Result: ${result}`, 'system').catch(() => { });
            }
            catch (err) {
                transactionManager_1.txManager.updateStatus(txId, 'failed', err.message);
                const prettyError = (0, formatter_1.formatTransactionError)(tx, err.message);
                await ctx.reply(prettyError);
                (0, reasoning_1.processUserInput)(`Transaction ${txId} FAILED via Telegram. Error: ${err.message}`, 'system').catch(() => { });
            }
        });
        bot.action(/^reject_(.+)$/, async (ctx) => {
            const txId = ctx.match[1];
            transactionManager_1.txManager.updateStatus(txId, 'rejected');
            (0, reasoning_1.processUserInput)(`Transaction ${txId} was REJECTED via Telegram. Acknowledge this briefly.`, 'system').catch(() => { });
            await ctx.answerCbQuery('Transaction cancelled.');
            await ctx.reply(`❌ Transaction cancelled.`);
            await ctx.editMessageReplyMarkup(undefined).catch(() => { });
        });
        bot.catch((err) => {
            console.error('[Telegram] Telegraf error:', err);
        });
        bot.launch().catch(err => {
            console.error('[Telegram] Connection failed (likely blocked by ISP or timeout):', err.message);
        });
        if (isPaired) {
            console.log('🤖 Telegram Bot is running and securely listening for your messages...');
        }
        // Enable graceful stop
        process.once('SIGINT', () => bot.stop('SIGINT'));
        process.once('SIGTERM', () => bot.stop('SIGTERM'));
    }
    catch (error) {
        console.error('[Telegram] Failed to initialize bot:', error);
    }
}
