/**
 * Billing handler for bundle purchases and subscription plan selection.
 *
 * This is deterministic bot code — the LLM agent is never involved in
 * payment flows. The handler manages:
 *
 * **Bundle flow** (`bundle_purchase` command):
 * 1. Admin dispatches bundle_purchase via heartbeat command
 * 2. Sends an amount selection prompt (inline keyboard) to the owner
 * 3. Listens for `billing_bundle_selected` events from Telegram
 * 4. Creates a one-time Stripe Checkout Session via the backend
 * 5. Sends the checkout URL to the owner
 *
 * **Subscription plan selection** (triggered by subscription gate, not a command):
 * The subscription gate sends the plan keyboard directly when the subscription
 * expires. This handler listens for `billing_plan_selected` events and creates
 * the corresponding Stripe Checkout Session.
 */
import { BUNDLE_ALLOWED_AMOUNTS } from "./types.js";
import { logger } from "../logger.js";
const MAX_CHECKOUT_RETRIES = 2;
const RETRY_DELAY_MS = 2_000;
function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
 * Billing handler for bundle purchases and subscription plan selection.
 * Instantiated once at startup; event listeners are wired in the constructor.
 */
export class BillingHandler {
    channelManager;
    ownerChatId;
    serviceClient;
    constructor(channelManager, ownerChatId, serviceClient) {
        this.channelManager = channelManager;
        this.ownerChatId = ownerChatId;
        this.serviceClient = serviceClient;
        // Wire up event listeners once at construction time.
        // billing_plan_selected: fired when the owner taps a plan in the subscription
        // gate keyboard (subscription-gate.ts sends the prompt, we handle the response).
        channelManager.on("billing_plan_selected", (event) => {
            void this.handlePlanSelected(event);
        });
        channelManager.on("billing_bundle_selected", (event) => {
            void this.handleBundleSelected(event);
        });
    }
    /**
     * Update the service client reference (e.g. after the client is lazily created).
     */
    setServiceClient(client) {
        this.serviceClient = client;
    }
    // ── Subscription plan selection (triggered by subscription gate) ──────
    /**
     * Called when the owner selects a subscription plan from the inline keyboard.
     * The keyboard is sent by the subscription gate (subscription-gate.ts),
     * not by a command handler.
     */
    async handlePlanSelected(event) {
        if (!this.serviceClient) {
            logger.warn("[billing] No service client — cannot create checkout session");
            await this.channelManager.sendMessage("telegram", String(event.chatId), "Payment is not configured. Please contact support.");
            return;
        }
        logger.system(`[billing] Plan selected: ${event.planId} by chat ${event.chatId}`);
        for (let attempt = 0; attempt <= MAX_CHECKOUT_RETRIES; attempt++) {
            try {
                const result = await this.serviceClient.createCheckoutSession(event.planId, event.chatId);
                if (result?.checkoutUrl) {
                    await this.channelManager.sendTelegramCheckoutLink(event.chatId, event.planName, result.checkoutUrl);
                    logger.system(`[billing] Checkout URL sent to chat ${event.chatId} for plan ${event.planId}`);
                    return;
                }
                if (attempt < MAX_CHECKOUT_RETRIES) {
                    logger.warn(`[billing] Checkout session attempt ${attempt + 1} failed, retrying...`);
                    await this.channelManager.sendMessage("telegram", String(event.chatId), "Payment setup failed, retrying...");
                    await sleep(RETRY_DELAY_MS);
                }
            }
            catch (err) {
                const errMsg = err instanceof Error ? err.message : String(err);
                logger.err(`[billing] Checkout session attempt ${attempt + 1} error: ${errMsg}`);
                if (attempt < MAX_CHECKOUT_RETRIES) {
                    await sleep(RETRY_DELAY_MS);
                }
            }
        }
        logger.err("[billing] All checkout session attempts failed");
        await this.channelManager.sendMessage("telegram", String(event.chatId), "Payment setup failed. Please try again later.");
    }
    // ── Bundle flow ──────────────────────────────────────────────────────
    /**
     * CommandHandler for `bundle_purchase`: sends amount picker to the owner.
     */
    handleBundlePurchase = async (_commandId, payload) => {
        const raw = (payload ?? {});
        const amounts = Array.isArray(raw.amounts)
            ? raw.amounts
            : [...BUNDLE_ALLOWED_AMOUNTS];
        const typedPayload = {
            reason: typeof raw.reason === "string" ? raw.reason : undefined,
            amounts,
        };
        logger.system(`[billing] Bundle purchase command received with ${typedPayload.amounts.length} amount(s)`);
        try {
            await this.channelManager.sendTelegramBundlePrompt(this.ownerChatId, typedPayload);
            return {
                status: "completed",
                result: JSON.stringify({ message: "Bundle prompt sent to owner" }),
            };
        }
        catch (err) {
            const errMsg = err instanceof Error ? err.message : String(err);
            logger.err(`[billing] Failed to send bundle prompt: ${errMsg}`);
            return {
                status: "failed",
                result: JSON.stringify({ error: errMsg }),
            };
        }
    };
    /**
     * Called when the owner selects a bundle amount from the inline keyboard.
     */
    async handleBundleSelected(event) {
        if (!this.serviceClient) {
            logger.warn("[billing] No service client — cannot create bundle purchase");
            await this.channelManager.sendMessage("telegram", String(event.chatId), "Payment is not configured. Please contact support.");
            return;
        }
        logger.system(`[billing] Bundle amount selected: $${event.amount} by chat ${event.chatId}`);
        for (let attempt = 0; attempt <= MAX_CHECKOUT_RETRIES; attempt++) {
            try {
                const result = await this.serviceClient.createBundlePurchase(event.amount, event.chatId);
                if (result?.checkoutUrl) {
                    await this.channelManager.sendTelegramCheckoutLink(event.chatId, `$${event.amount} Bundle Top-Up`, result.checkoutUrl);
                    logger.system(`[billing] Bundle checkout URL sent to chat ${event.chatId} for $${event.amount}`);
                    return;
                }
                if (attempt < MAX_CHECKOUT_RETRIES) {
                    logger.warn(`[billing] Bundle checkout attempt ${attempt + 1} failed, retrying...`);
                    await this.channelManager.sendMessage("telegram", String(event.chatId), "Bundle purchase setup failed, retrying...");
                    await sleep(RETRY_DELAY_MS);
                }
            }
            catch (err) {
                const errMsg = err instanceof Error ? err.message : String(err);
                logger.err(`[billing] Bundle checkout attempt ${attempt + 1} error: ${errMsg}`);
                if (attempt < MAX_CHECKOUT_RETRIES) {
                    await sleep(RETRY_DELAY_MS);
                }
            }
        }
        logger.err("[billing] All bundle checkout attempts failed");
        await this.channelManager.sendMessage("telegram", String(event.chatId), "Bundle purchase setup failed. Please try again later.");
    }
}
//# sourceMappingURL=billing-handler.js.map