"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensurePremiumAccess = exports.registerSubscriptionCommands = void 0;
const telegraf_1 = require("telegraf");
const qrcode_1 = __importDefault(require("qrcode"));
const types_js_1 = require("../domain/subscriptions/types.js");
const menu_js_1 = require("./menu.js");
const planPrefix = "subscription:plan:";
const networkPrefix = "subscription:network:";
const countdownUpdateMs = 30 * 1000;
const registerSubscriptionCommands = (bot, subscriptionService, adminTelegramIds, logger) => {
    const showPlatformOptions = async (ctx) => {
        if (!subscriptionService.isEnabled()) {
            await ctx.reply("Subscription payments are not configured yet. Please contact support.");
            return;
        }
        await ctx.reply("Select a platform to view its subscription plans:", (0, menu_js_1.platformsKeyboard)());
    };
    bot.command(["subscribe", "plans", "renew"], showPlatformOptions);
    for (const platform of types_js_1.PLATFORM_OPTIONS) {
        bot.action((0, menu_js_1.subscribePlatformCallback)(platform.code), async (ctx) => {
            await ctx.answerCbQuery();
            await ctx.reply(`Choose a subscription plan for ${platform.name}:`, platformPlansKeyboard(platform.code));
        });
        bot.action((0, menu_js_1.mySubscriptionCallback)(platform.code), async (ctx) => {
            await ctx.answerCbQuery();
            await replyWithSubscriptionSummary(ctx, subscriptionService, platform.code);
        });
    }
    for (const plan of types_js_1.PAYMENT_PLANS) {
        bot.action(`${planPrefix}${plan.code}`, async (ctx) => {
            await ctx.answerCbQuery("Choose a payment network");
            await ctx.reply(`Selected ${plan.name}. Choose the USDT network:`, networksKeyboard(plan.code));
        });
    }
    for (const plan of types_js_1.PAYMENT_PLANS) {
        for (const network of types_js_1.PAYMENT_NETWORKS) {
            bot.action(`${networkPrefix}${plan.code}:${network}`, async (ctx) => {
                await ctx.answerCbQuery("Preparing payment request...");
                try {
                    const telegramId = await subscriptionService.upsertUserFromContext(ctx);
                    if (!telegramId) {
                        await ctx.reply("I could not identify your Telegram account. Please try again from Telegram directly.");
                        return;
                    }
                    const result = await subscriptionService.createOrGetPaymentRequest({
                        telegramId,
                        username: ctx.from?.username,
                        planCode: plan.code,
                        network
                    });
                    await sendPaymentRequest(ctx, subscriptionService, result.transaction, result.decimals, result.reused, logger);
                }
                catch (error) {
                    logger.warn("Could not create subscription payment request.", serializeError(error));
                    await ctx.reply(error instanceof Error ? error.message : "Could not create a payment request right now.");
                }
            });
        }
    }
    bot.command(["payment_status", "my_subscription"], async (ctx) => {
        await replyWithSubscriptionSummary(ctx, subscriptionService);
    });
    bot.command("admin_subscriptions", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        await ctx.reply(await subscriptionService.listSubscriptions());
    });
    bot.command("admin_user_subscription", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        const [telegramId, platformCode] = args(ctx);
        if (!telegramId) {
            await ctx.reply("Usage: /admin_user_subscription <telegramId> [platform]");
            return;
        }
        await ctx.reply(await subscriptionService.getUserSubscription(telegramId, platformCode));
    });
    bot.command("admin_extend_subscription", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        const [telegramId, platformCode, daysText] = args(ctx);
        const days = Number(daysText);
        if (!telegramId || !platformCode || !Number.isInteger(days) || days <= 0) {
            await ctx.reply("Usage: /admin_extend_subscription <telegramId> <platform> <days>");
            return;
        }
        if (!(0, types_js_1.getPlatformByCode)(platformCode)) {
            await ctx.reply(`Unknown platform: ${platformCode}`);
            return;
        }
        await subscriptionService.extendSubscription(telegramId, platformCode, days);
        await ctx.reply(`Extended ${platformCode} subscription for ${telegramId} by ${days} days.`);
    });
    bot.command("admin_grant_lifetime", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        const [telegramId, platformCode] = args(ctx);
        if (!telegramId || !platformCode) {
            await ctx.reply("Usage: /admin_grant_lifetime <telegramId> <platform>");
            return;
        }
        if (!(0, types_js_1.getPlatformByCode)(platformCode)) {
            await ctx.reply(`Unknown platform: ${platformCode}`);
            return;
        }
        await subscriptionService.grantLifetime(telegramId, platformCode);
        await ctx.reply(`Granted ${platformCode} lifetime subscription to ${telegramId}.`);
    });
    bot.command("admin_revoke_subscription", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        const [telegramId, platformCode] = args(ctx);
        if (!telegramId || !platformCode) {
            await ctx.reply("Usage: /admin_revoke_subscription <telegramId> <platform>");
            return;
        }
        if (!(0, types_js_1.getPlatformByCode)(platformCode)) {
            await ctx.reply(`Unknown platform: ${platformCode}`);
            return;
        }
        await subscriptionService.revokeSubscription(telegramId, platformCode);
        await ctx.reply(`Revoked ${platformCode} subscription for ${telegramId}.`);
    });
    bot.command("admin_payments", async (ctx) => {
        if (!(await assertAdmin(ctx, adminTelegramIds)))
            return;
        await ctx.reply(await subscriptionService.listPayments());
    });
};
exports.registerSubscriptionCommands = registerSubscriptionCommands;
const ensurePremiumAccess = async (ctx, subscriptionService, platformCode) => {
    const telegramId = await subscriptionService.upsertUserFromContext(ctx);
    if (!telegramId) {
        await ctx.reply("I could not identify your Telegram account.");
        return false;
    }
    if (await subscriptionService.checkActiveSubscription(telegramId, platformCode)) {
        return true;
    }
    if (!subscriptionService.isEnabled()) {
        await ctx.reply("Premium access requires an active subscription, but subscription payments are not configured yet. Please contact support.");
        return false;
    }
    const platform = (0, types_js_1.getPlatformByCode)(platformCode);
    await ctx.reply(`Access to ${platform?.name ?? platformCode} requires an active subscription.`, subscribePlatformKeyboard(platformCode));
    return false;
};
exports.ensurePremiumAccess = ensurePremiumAccess;
const subscribePlatformKeyboard = (platformCode) => telegraf_1.Markup.inlineKeyboard([
    [telegraf_1.Markup.button.callback("💳 Subscribe", (0, menu_js_1.subscribePlatformCallback)(platformCode))],
    [telegraf_1.Markup.button.callback("🔙 Back to Markets", (0, menu_js_1.marketCallback)("back"))]
]);
const platformPlansKeyboard = (platformCode) => telegraf_1.Markup.inlineKeyboard((0, types_js_1.getPlansForPlatform)(platformCode).map((plan) => [
    telegraf_1.Markup.button.callback(`${plan.name} — ${plan.amountUsdt} USDT (${plan.dailyRequestLimit} req/day)`, `${planPrefix}${plan.code}`)
]));
const networksKeyboard = (planCode) => telegraf_1.Markup.inlineKeyboard(types_js_1.PAYMENT_NETWORKS.map((network) => [
    telegraf_1.Markup.button.callback(types_js_1.NETWORK_LABELS[network].name, `${networkPrefix}${planCode}:${network}`)
]));
const replyWithSubscriptionSummary = async (ctx, subscriptionService, platformCode) => {
    const telegramId = await subscriptionService.upsertUserFromContext(ctx);
    if (!telegramId) {
        await ctx.reply("I could not identify your Telegram account.");
        return;
    }
    await ctx.reply(await subscriptionService.getSubscriptionSummary(telegramId, platformCode));
};
const sendPaymentRequest = async (ctx, subscriptionService, transaction, decimals, reused, logger) => {
    const caption = subscriptionService.paymentRequestMessage(transaction, decimals, reused);
    try {
        const qrCode = await qrcode_1.default.toBuffer(transaction.walletAddress, {
            errorCorrectionLevel: "M",
            margin: 2,
            scale: 8,
            type: "png"
        });
        const message = await ctx.replyWithPhoto({ source: qrCode, filename: `payment-${transaction.network}-${transaction.walletAddress}.png` }, { caption });
        startPaymentCountdown(ctx, subscriptionService, transaction, decimals, reused, message.message_id, logger);
    }
    catch (error) {
        logger.warn("Could not send subscription payment QR code. Falling back to text details.", serializeError(error));
        await ctx.reply(caption);
    }
};
const startPaymentCountdown = (ctx, subscriptionService, transaction, decimals, reused, messageId, logger) => {
    const chatId = ctx.chat?.id;
    if (!chatId)
        return;
    const timer = setInterval(() => {
        const secondsRemaining = Math.max(0, Math.ceil((transaction.expiresAt.getTime() - Date.now()) / 1000));
        const caption = subscriptionService.paymentRequestMessage(transaction, decimals, reused);
        ctx.telegram
            .editMessageCaption(chatId, messageId, undefined, caption)
            .catch((error) => logger.warn("Could not update subscription payment countdown.", serializeError(error)));
        if (secondsRemaining <= 0) {
            clearInterval(timer);
        }
    }, countdownUpdateMs);
    timer.unref();
};
const assertAdmin = async (ctx, adminTelegramIds) => {
    const telegramId = ctx.from?.id ? String(ctx.from.id) : "";
    if (telegramId && adminTelegramIds.includes(telegramId))
        return true;
    await ctx.reply("This admin command is not available for your Telegram account.");
    return false;
};
const args = (ctx) => {
    const message = ctx.message;
    const text = message?.text ?? "";
    return text.split(/\s+/).slice(1).filter(Boolean);
};
const serializeError = (error) => {
    if (error instanceof Error)
        return { name: error.name, message: error.message, stack: error.stack };
    return { error };
};
