"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const bot_client_js_1 = require("./bot-client.js");
// Mock undici fetch
const mockFetch = vitest_1.vi.fn();
vitest_1.vi.mock('undici', () => ({ fetch: (...args) => mockFetch(...args) }));
// Mock logger
vitest_1.vi.mock('../../utils/logger.js', () => ({
    createModuleLogger: () => ({
        debug: vitest_1.vi.fn(),
        info: vitest_1.vi.fn(),
        warn: vitest_1.vi.fn(),
        error: vitest_1.vi.fn(),
    }),
}));
function makeOkResponse(result) {
    return {
        ok: true,
        status: 200,
        json: () => Promise.resolve({ ok: true, result }),
    };
}
function makeApiErrorResponse(errorCode, description) {
    return {
        ok: true,
        status: 200,
        json: () => Promise.resolve({
            ok: false,
            error_code: errorCode,
            description,
        }),
    };
}
const BOT_INFO = {
    id: 123456789,
    is_bot: true,
    first_name: 'TestBot',
    username: 'test_bot',
};
(0, vitest_1.describe)('TelegramBotClient', () => {
    let client;
    (0, vitest_1.beforeEach)(() => {
        client = new bot_client_js_1.TelegramBotClient('test-token-123', { initialBackoffMs: 1 });
        mockFetch.mockReset();
    });
    (0, vitest_1.describe)('constructor', () => {
        (0, vitest_1.it)('throws if token is empty', () => {
            (0, vitest_1.expect)(() => new bot_client_js_1.TelegramBotClient('')).toThrow('Telegram bot token is required');
        });
        (0, vitest_1.it)('creates instance with valid token', () => {
            (0, vitest_1.expect)(new bot_client_js_1.TelegramBotClient('valid-token')).toBeInstanceOf(bot_client_js_1.TelegramBotClient);
        });
    });
    (0, vitest_1.describe)('getMe', () => {
        (0, vitest_1.it)('returns bot info on success', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(BOT_INFO));
            const result = await client.getMe();
            (0, vitest_1.expect)(result).toEqual(BOT_INFO);
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledOnce();
            const [url, options] = mockFetch.mock.calls[0];
            (0, vitest_1.expect)(url).toBe('https://api.telegram.org/bottest-token-123/getMe');
            (0, vitest_1.expect)(options.method).toBe('POST');
        });
    });
    (0, vitest_1.describe)('sendMessage', () => {
        (0, vitest_1.it)('sends message with correct params', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse({ message_id: 1 }));
            await client.sendMessage(12345, 'Hello!');
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.chat_id).toBe(12345);
            (0, vitest_1.expect)(body.text).toBe('Hello!');
        });
        (0, vitest_1.it)('includes optional params when provided', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse({ message_id: 1 }));
            await client.sendMessage(12345, 'Hello!', {
                parse_mode: 'HTML',
                reply_to_message_id: 99,
            });
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.parse_mode).toBe('HTML');
            (0, vitest_1.expect)(body.reply_to_message_id).toBe(99);
        });
    });
    (0, vitest_1.describe)('sendChatAction', () => {
        (0, vitest_1.it)('sends typing action', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            const result = await client.sendChatAction(12345, 'typing');
            (0, vitest_1.expect)(result).toBe(true);
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.chat_id).toBe(12345);
            (0, vitest_1.expect)(body.action).toBe('typing');
        });
    });
    (0, vitest_1.describe)('sendPaidMedia', () => {
        (0, vitest_1.it)('sends paid media request', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse({ message_id: 2 }));
            const request = {
                chat_id: 12345,
                star_count: 50,
                media: [{ type: 'photo', media: 'https://example.com/photo.jpg' }],
                caption: 'Exclusive content',
            };
            await client.sendPaidMedia(request);
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.chat_id).toBe(12345);
            (0, vitest_1.expect)(body.star_count).toBe(50);
            (0, vitest_1.expect)(body.media).toEqual([{ type: 'photo', media: 'https://example.com/photo.jpg' }]);
            (0, vitest_1.expect)(body.caption).toBe('Exclusive content');
        });
    });
    (0, vitest_1.describe)('createChatInviteLink', () => {
        (0, vitest_1.it)('creates invite link with options', async () => {
            const inviteLink = { invite_link: 'https://t.me/+abc123' };
            mockFetch.mockResolvedValueOnce(makeOkResponse(inviteLink));
            const result = await client.createChatInviteLink(-100123, {
                name: 'VIP Link',
                member_limit: 100,
            });
            (0, vitest_1.expect)(result).toEqual(inviteLink);
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.chat_id).toBe(-100123);
            (0, vitest_1.expect)(body.name).toBe('VIP Link');
            (0, vitest_1.expect)(body.member_limit).toBe(100);
        });
    });
    (0, vitest_1.describe)('setWebhook', () => {
        (0, vitest_1.it)('sets webhook URL', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            const result = await client.setWebhook('https://example.com/webhook');
            (0, vitest_1.expect)(result).toBe(true);
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.url).toBe('https://example.com/webhook');
        });
        (0, vitest_1.it)('includes optional webhook options', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            await client.setWebhook('https://example.com/webhook', {
                max_connections: 40,
                allowed_updates: ['message', 'pre_checkout_query'],
                secret_token: 'secret-123',
            });
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.max_connections).toBe(40);
            (0, vitest_1.expect)(body.allowed_updates).toEqual(['message', 'pre_checkout_query']);
            (0, vitest_1.expect)(body.secret_token).toBe('secret-123');
        });
    });
    (0, vitest_1.describe)('deleteWebhook', () => {
        (0, vitest_1.it)('deletes webhook', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            const result = await client.deleteWebhook();
            (0, vitest_1.expect)(result).toBe(true);
            const [url] = mockFetch.mock.calls[0];
            (0, vitest_1.expect)(url).toBe('https://api.telegram.org/bottest-token-123/deleteWebhook');
        });
    });
    (0, vitest_1.describe)('answerPreCheckoutQuery', () => {
        (0, vitest_1.it)('answers pre-checkout query with ok=true', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            const result = await client.answerPreCheckoutQuery('query-123', true);
            (0, vitest_1.expect)(result).toBe(true);
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.pre_checkout_query_id).toBe('query-123');
            (0, vitest_1.expect)(body.ok).toBe(true);
            (0, vitest_1.expect)(body).not.toHaveProperty('error_message');
        });
        (0, vitest_1.it)('answers pre-checkout query with ok=false and error message', async () => {
            mockFetch.mockResolvedValueOnce(makeOkResponse(true));
            await client.answerPreCheckoutQuery('query-456', false, 'Item unavailable');
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            (0, vitest_1.expect)(body.pre_checkout_query_id).toBe('query-456');
            (0, vitest_1.expect)(body.ok).toBe(false);
            (0, vitest_1.expect)(body.error_message).toBe('Item unavailable');
        });
    });
    (0, vitest_1.describe)('retry logic', () => {
        (0, vitest_1.it)('retries on 500 errors with exponential backoff', async () => {
            mockFetch
                .mockResolvedValueOnce(makeApiErrorResponse(500, 'Internal Server Error'))
                .mockResolvedValueOnce(makeApiErrorResponse(502, 'Bad Gateway'))
                .mockResolvedValueOnce(makeOkResponse(BOT_INFO));
            const result = await client.getMe();
            (0, vitest_1.expect)(result).toEqual(BOT_INFO);
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledTimes(3);
        });
        (0, vitest_1.it)('retries on 429 rate limit errors', async () => {
            mockFetch
                .mockResolvedValueOnce(makeApiErrorResponse(429, 'Too Many Requests'))
                .mockResolvedValueOnce(makeOkResponse(true));
            const result = await client.sendChatAction(123, 'typing');
            (0, vitest_1.expect)(result).toBe(true);
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledTimes(2);
        });
        (0, vitest_1.it)('throws immediately on 4xx client errors (not 429)', async () => {
            mockFetch.mockResolvedValueOnce(makeApiErrorResponse(400, 'Bad Request'));
            await (0, vitest_1.expect)(client.getMe()).rejects.toThrow('Telegram API error: 400');
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledOnce();
        });
        (0, vitest_1.it)('throws after exhausting all retries', async () => {
            mockFetch
                .mockResolvedValueOnce(makeApiErrorResponse(500, 'Internal Server Error'))
                .mockResolvedValueOnce(makeApiErrorResponse(500, 'Internal Server Error'))
                .mockResolvedValueOnce(makeApiErrorResponse(500, 'Internal Server Error'));
            await (0, vitest_1.expect)(client.getMe()).rejects.toThrow('Telegram API error: 500');
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledTimes(3);
        });
        (0, vitest_1.it)('retries on network errors', async () => {
            mockFetch
                .mockRejectedValueOnce(new Error('fetch failed'))
                .mockResolvedValueOnce(makeOkResponse(BOT_INFO));
            const result = await client.getMe();
            (0, vitest_1.expect)(result).toEqual(BOT_INFO);
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledTimes(2);
        });
        (0, vitest_1.it)('throws after all network error retries exhausted', async () => {
            mockFetch
                .mockRejectedValueOnce(new Error('fetch failed'))
                .mockRejectedValueOnce(new Error('fetch failed'))
                .mockRejectedValueOnce(new Error('fetch failed'));
            await (0, vitest_1.expect)(client.getMe()).rejects.toThrow('fetch failed');
            (0, vitest_1.expect)(mockFetch).toHaveBeenCalledTimes(3);
        });
    });
});
//# sourceMappingURL=bot-client.test.js.map