"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const webhook_handler_js_1 = require("./webhook-handler.js");
vitest_1.vi.mock('../../utils/index.js', () => ({
    createModuleLogger: () => ({
        debug: vitest_1.vi.fn(),
        info: vitest_1.vi.fn(),
        warn: vitest_1.vi.fn(),
        error: vitest_1.vi.fn(),
    }),
}));
const BOT_TOKEN = 'bot-token-123';
const BOT_TOKEN_2 = 'bot-token-456';
function makeTelegramMessage(overrides = {}) {
    return {
        message_id: 1,
        chat: { id: 100, type: 'private' },
        date: Math.floor(Date.now() / 1000),
        text: 'Hello',
        from: { id: 42, is_bot: false, first_name: 'Test' },
        ...overrides,
    };
}
function makePreCheckoutQuery(overrides = {}) {
    return {
        id: 'pchk-1',
        from: { id: 42, is_bot: false, first_name: 'Test' },
        currency: 'XTR',
        total_amount: 100,
        invoice_payload: 'image-abc',
        ...overrides,
    };
}
function makeSuccessfulPayment(overrides = {}) {
    return {
        currency: 'XTR',
        total_amount: 100,
        invoice_payload: 'image-abc',
        telegram_payment_charge_id: 'charge-1',
        provider_payment_charge_id: 'provider-1',
        ...overrides,
    };
}
(0, vitest_1.describe)('WebhookHandler', () => {
    let handler;
    (0, vitest_1.beforeEach)(() => {
        handler = new webhook_handler_js_1.WebhookHandler(new Map([[BOT_TOKEN, 'char-1']]));
    });
    (0, vitest_1.describe)('constructor', () => {
        (0, vitest_1.it)('accepts a Map of tokens', () => {
            const h = new webhook_handler_js_1.WebhookHandler(new Map([['tok1', 'c1'], ['tok2', 'c2']]));
            (0, vitest_1.expect)(h.validateToken('tok1')).toBe(true);
            (0, vitest_1.expect)(h.validateToken('tok2')).toBe(true);
        });
        (0, vitest_1.it)('accepts a Set of tokens', () => {
            const h = new webhook_handler_js_1.WebhookHandler(new Set(['tok1', 'tok2']));
            (0, vitest_1.expect)(h.validateToken('tok1')).toBe(true);
        });
        (0, vitest_1.it)('accepts an array of tokens', () => {
            const h = new webhook_handler_js_1.WebhookHandler(['tok1', 'tok2']);
            (0, vitest_1.expect)(h.validateToken('tok1')).toBe(true);
        });
    });
    (0, vitest_1.describe)('validateToken', () => {
        (0, vitest_1.it)('returns true for registered token', () => {
            (0, vitest_1.expect)(handler.validateToken(BOT_TOKEN)).toBe(true);
        });
        (0, vitest_1.it)('returns false for unregistered token', () => {
            (0, vitest_1.expect)(handler.validateToken('unknown-token')).toBe(false);
        });
    });
    (0, vitest_1.describe)('registerToken / unregisterToken', () => {
        (0, vitest_1.it)('registers a new token', () => {
            (0, vitest_1.expect)(handler.validateToken(BOT_TOKEN_2)).toBe(false);
            handler.registerToken(BOT_TOKEN_2);
            (0, vitest_1.expect)(handler.validateToken(BOT_TOKEN_2)).toBe(true);
        });
        (0, vitest_1.it)('unregisters a token and removes its handlers', () => {
            const msgHandler = vitest_1.vi.fn();
            handler.onMessage(BOT_TOKEN, msgHandler);
            handler.unregisterToken(BOT_TOKEN);
            (0, vitest_1.expect)(handler.validateToken(BOT_TOKEN)).toBe(false);
        });
        (0, vitest_1.it)('unregistering a non-existent token does not throw', () => {
            (0, vitest_1.expect)(() => handler.unregisterToken('nonexistent')).not.toThrow();
        });
    });
    (0, vitest_1.describe)('handleTelegramWebhook', () => {
        (0, vitest_1.it)('rejects missing bot token', async () => {
            const update = { update_id: 1, message: makeTelegramMessage() };
            const result = await handler.handleTelegramWebhook('', update);
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Missing bot token' });
        });
        (0, vitest_1.it)('rejects invalid bot token', async () => {
            const update = { update_id: 1, message: makeTelegramMessage() };
            const result = await handler.handleTelegramWebhook('wrong-token', update);
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid bot token' });
        });
        (0, vitest_1.it)('rejects invalid payload (missing update_id)', async () => {
            const result = await handler.handleTelegramWebhook(BOT_TOKEN, {});
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid payload' });
        });
        (0, vitest_1.it)('rejects null payload', async () => {
            const result = await handler.handleTelegramWebhook(BOT_TOKEN, null);
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid payload' });
        });
        (0, vitest_1.describe)('message handling', () => {
            (0, vitest_1.it)('routes text messages to onMessage handler', async () => {
                const msgHandler = vitest_1.vi.fn();
                handler.onMessage(BOT_TOKEN, msgHandler);
                const message = makeTelegramMessage({ text: 'Hi there' });
                const update = { update_id: 1, message };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
                (0, vitest_1.expect)(msgHandler).toHaveBeenCalledWith(BOT_TOKEN, message);
            });
            (0, vitest_1.it)('succeeds even without a registered message handler', async () => {
                const update = { update_id: 1, message: makeTelegramMessage() };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
            });
            (0, vitest_1.it)('handles async message handlers', async () => {
                const msgHandler = vitest_1.vi.fn().mockResolvedValue(undefined);
                handler.onMessage(BOT_TOKEN, msgHandler);
                const update = { update_id: 1, message: makeTelegramMessage() };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
                (0, vitest_1.expect)(msgHandler).toHaveBeenCalledOnce();
            });
        });
        (0, vitest_1.describe)('pre_checkout_query handling', () => {
            (0, vitest_1.it)('routes pre_checkout_query to handler', async () => {
                const pchkHandler = vitest_1.vi.fn();
                handler.onPreCheckoutQuery(BOT_TOKEN, pchkHandler);
                const query = makePreCheckoutQuery();
                const update = { update_id: 2, pre_checkout_query: query };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
                (0, vitest_1.expect)(pchkHandler).toHaveBeenCalledWith(BOT_TOKEN, query);
            });
            (0, vitest_1.it)('succeeds without a registered pre_checkout handler', async () => {
                const update = { update_id: 2, pre_checkout_query: makePreCheckoutQuery() };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
            });
        });
        (0, vitest_1.describe)('successful_payment handling', () => {
            (0, vitest_1.it)('routes successful_payment to handler', async () => {
                const payHandler = vitest_1.vi.fn();
                handler.onSuccessfulPayment(BOT_TOKEN, payHandler);
                const payment = makeSuccessfulPayment();
                const message = makeTelegramMessage({ successful_payment: payment });
                const update = { update_id: 3, message };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
                (0, vitest_1.expect)(payHandler).toHaveBeenCalledWith(BOT_TOKEN, payment, message);
            });
            (0, vitest_1.it)('does NOT call onMessage when successful_payment is present', async () => {
                const msgHandler = vitest_1.vi.fn();
                const payHandler = vitest_1.vi.fn();
                handler.onMessage(BOT_TOKEN, msgHandler);
                handler.onSuccessfulPayment(BOT_TOKEN, payHandler);
                const payment = makeSuccessfulPayment();
                const message = makeTelegramMessage({ successful_payment: payment });
                const update = { update_id: 3, message };
                await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(payHandler).toHaveBeenCalledOnce();
                (0, vitest_1.expect)(msgHandler).not.toHaveBeenCalled();
            });
        });
        (0, vitest_1.describe)('combined updates', () => {
            (0, vitest_1.it)('handles pre_checkout_query and message in same update', async () => {
                const msgHandler = vitest_1.vi.fn();
                const pchkHandler = vitest_1.vi.fn();
                handler.onMessage(BOT_TOKEN, msgHandler);
                handler.onPreCheckoutQuery(BOT_TOKEN, pchkHandler);
                const update = {
                    update_id: 4,
                    pre_checkout_query: makePreCheckoutQuery(),
                    message: makeTelegramMessage(),
                };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: true });
                (0, vitest_1.expect)(pchkHandler).toHaveBeenCalledOnce();
                (0, vitest_1.expect)(msgHandler).toHaveBeenCalledOnce();
            });
        });
        (0, vitest_1.describe)('error handling', () => {
            (0, vitest_1.it)('returns error when message handler throws', async () => {
                handler.onMessage(BOT_TOKEN, () => { throw new Error('handler failed'); });
                const update = { update_id: 5, message: makeTelegramMessage() };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'handler failed' });
            });
            (0, vitest_1.it)('returns error when async handler rejects', async () => {
                handler.onMessage(BOT_TOKEN, async () => { throw new Error('async fail'); });
                const update = { update_id: 6, message: makeTelegramMessage() };
                const result = await handler.handleTelegramWebhook(BOT_TOKEN, update);
                (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'async fail' });
            });
        });
    });
    (0, vitest_1.describe)('handleKIEWebhook', () => {
        (0, vitest_1.it)('processes a completed task', async () => {
            const kieHandler = vitest_1.vi.fn();
            handler.onKIEComplete(kieHandler);
            const payload = {
                taskId: 'task-1',
                status: 'completed',
                resultUrl: 'https://cdn.kie.ai/result.jpg',
            };
            const result = await handler.handleKIEWebhook(payload);
            (0, vitest_1.expect)(result).toEqual({ ok: true });
            (0, vitest_1.expect)(kieHandler).toHaveBeenCalledWith(payload);
        });
        (0, vitest_1.it)('processes a failed task', async () => {
            const kieHandler = vitest_1.vi.fn();
            handler.onKIEComplete(kieHandler);
            const payload = {
                taskId: 'task-2',
                status: 'failed',
                error: 'Content policy violation',
            };
            const result = await handler.handleKIEWebhook(payload);
            (0, vitest_1.expect)(result).toEqual({ ok: true });
            (0, vitest_1.expect)(kieHandler).toHaveBeenCalledWith(payload);
        });
        (0, vitest_1.it)('calls multiple KIE handlers', async () => {
            const handler1 = vitest_1.vi.fn();
            const handler2 = vitest_1.vi.fn();
            handler.onKIEComplete(handler1);
            handler.onKIEComplete(handler2);
            const payload = { taskId: 'task-3', status: 'processing' };
            await handler.handleKIEWebhook(payload);
            (0, vitest_1.expect)(handler1).toHaveBeenCalledOnce();
            (0, vitest_1.expect)(handler2).toHaveBeenCalledOnce();
        });
        (0, vitest_1.it)('rejects null payload', async () => {
            const result = await handler.handleKIEWebhook(null);
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid payload' });
        });
        (0, vitest_1.it)('rejects non-object payload', async () => {
            const result = await handler.handleKIEWebhook('not-an-object');
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid payload' });
        });
        (0, vitest_1.it)('rejects payload without taskId', async () => {
            const result = await handler.handleKIEWebhook({ status: 'completed' });
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Missing taskId' });
        });
        (0, vitest_1.it)('rejects payload without status', async () => {
            const result = await handler.handleKIEWebhook({ taskId: 'task-1' });
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Missing status' });
        });
        (0, vitest_1.it)('rejects payload with invalid status', async () => {
            const result = await handler.handleKIEWebhook({ taskId: 'task-1', status: 'unknown' });
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'Invalid status' });
        });
        (0, vitest_1.it)('returns error when KIE handler throws', async () => {
            handler.onKIEComplete(() => { throw new Error('kie handler failed'); });
            const payload = { taskId: 'task-4', status: 'completed' };
            const result = await handler.handleKIEWebhook(payload);
            (0, vitest_1.expect)(result).toEqual({ ok: false, error: 'kie handler failed' });
        });
        (0, vitest_1.it)('succeeds without any registered KIE handlers', async () => {
            const payload = { taskId: 'task-5', status: 'completed' };
            const result = await handler.handleKIEWebhook(payload);
            (0, vitest_1.expect)(result).toEqual({ ok: true });
        });
        (0, vitest_1.it)('strips unknown fields from payload', async () => {
            const kieHandler = vitest_1.vi.fn();
            handler.onKIEComplete(kieHandler);
            const payload = { taskId: 'task-6', status: 'completed', resultUrl: 'https://example.com/img.jpg', extraField: 'ignored' };
            await handler.handleKIEWebhook(payload);
            const received = kieHandler.mock.calls[0][0];
            (0, vitest_1.expect)(received.taskId).toBe('task-6');
            (0, vitest_1.expect)(received.status).toBe('completed');
            (0, vitest_1.expect)(received.resultUrl).toBe('https://example.com/img.jpg');
            (0, vitest_1.expect)(received['extraField']).toBeUndefined();
        });
    });
});
//# sourceMappingURL=webhook-handler.test.js.map