"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
// Mock GramJS TelegramClient
const mockInvoke = vitest_1.vi.fn();
const mockSendMessage = vitest_1.vi.fn();
const mockSendFile = vitest_1.vi.fn();
const mockConnect = vitest_1.vi.fn();
const mockDisconnect = vitest_1.vi.fn();
const mockStart = vitest_1.vi.fn();
const mockAddEventHandler = vitest_1.vi.fn();
const mockSessionSave = vitest_1.vi.fn().mockReturnValue('test-session');
const mockGetEntity = vitest_1.vi.fn();
const mockGetInputEntity = vitest_1.vi.fn();
vitest_1.vi.mock('telegram', () => ({
    TelegramClient: vitest_1.vi.fn().mockImplementation(() => ({
        invoke: mockInvoke,
        sendMessage: mockSendMessage,
        sendFile: mockSendFile,
        connect: mockConnect,
        disconnect: mockDisconnect,
        start: mockStart,
        addEventHandler: mockAddEventHandler,
        session: { save: mockSessionSave },
        getEntity: mockGetEntity,
        getInputEntity: mockGetInputEntity,
    })),
}));
vitest_1.vi.mock('telegram/sessions/index.js', () => ({
    StringSession: vitest_1.vi.fn().mockImplementation((s) => ({ _session: s })),
}));
vitest_1.vi.mock('telegram/events/index.js', () => ({
    NewMessage: vitest_1.vi.fn(),
    NewMessageEvent: vitest_1.vi.fn(),
}));
vitest_1.vi.mock('telegram/tl/index.js', () => {
    // Define MockChatInviteExported inside the factory to avoid hoisting issues
    class ChatInviteExported {
        link;
        constructor(args) {
            this.link = args.link;
        }
    }
    return {
        Api: {
            channels: {
                CreateChannel: vitest_1.vi.fn().mockImplementation((args) => ({ _: 'channels.CreateChannel', ...args })),
            },
            messages: {
                CreateChat: vitest_1.vi.fn().mockImplementation((args) => ({ _: 'messages.CreateChat', ...args })),
                ExportChatInvite: vitest_1.vi.fn().mockImplementation((args) => ({ _: 'messages.ExportChatInvite', ...args })),
                SetTyping: vitest_1.vi.fn().mockImplementation((args) => ({ _: 'messages.SetTyping', ...args })),
            },
            Updates: class {
            },
            ChatInviteExported,
            SendMessageTypingAction: vitest_1.vi.fn(),
        },
    };
});
vitest_1.vi.mock('telegram/client/uploads.js', () => ({
    CustomFile: vitest_1.vi.fn().mockImplementation((name, size, _, buffer) => ({
        name, size, buffer,
    })),
}));
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(),
    }),
}));
vitest_1.vi.mock('../../utils/config.js', () => ({
    config: {
        telegramApiId: 12345,
        telegramApiHash: 'testhash',
        dataDir: '/tmp/test-data',
    },
}));
// Import after mocks are set up
const client_js_1 = require("./client.js");
const index_js_1 = require("telegram/tl/index.js");
function createClient(overrides) {
    return new client_js_1.UserbotClient({
        characterId: 'char-1',
        phoneNumber: '+1234567890',
        telegramApiId: 12345,
        telegramApiHash: 'testhash',
        ...overrides,
    });
}
/** Simulate connecting the client by calling reconnect (sets connected = true) */
async function connectClient(client) {
    mockConnect.mockResolvedValueOnce(undefined);
    await client.reconnect();
}
(0, vitest_1.describe)('UserbotClient', () => {
    (0, vitest_1.beforeEach)(() => {
        vitest_1.vi.clearAllMocks();
    });
    (0, vitest_1.describe)('createGroup', () => {
        (0, vitest_1.it)('throws if not connected', async () => {
            const client = createClient();
            await (0, vitest_1.expect)(client.createGroup('Test Group')).rejects.toThrow('Userbot not connected');
        });
        (0, vitest_1.it)('creates a normal group via messages.CreateChat', async () => {
            const client = createClient();
            await connectClient(client);
            const mockChat = { id: { valueOf: () => 123456 } };
            mockInvoke
                .mockResolvedValueOnce({ chats: [mockChat] }) // CreateChat
                .mockResolvedValueOnce(Object.assign(Object.create(index_js_1.Api.ChatInviteExported.prototype), { link: 'https://t.me/+abc' }));
            const result = await client.createGroup('Test Group', 'A test group');
            (0, vitest_1.expect)(result.chatId).toBe(123456);
            (0, vitest_1.expect)(result.inviteLink).toBe('https://t.me/+abc');
            (0, vitest_1.expect)(mockInvoke).toHaveBeenCalledTimes(2);
        });
        (0, vitest_1.it)('creates a supergroup via channels.CreateChannel with megagroup flag', async () => {
            const client = createClient();
            await connectClient(client);
            const mockChannel = { id: { valueOf: () => 789012 } };
            mockInvoke
                .mockResolvedValueOnce({ chats: [mockChannel] }) // CreateChannel
                .mockResolvedValueOnce(Object.assign(Object.create(index_js_1.Api.ChatInviteExported.prototype), { link: 'https://t.me/+xyz' }));
            const result = await client.createGroup('Super Group', 'A supergroup', true);
            (0, vitest_1.expect)(result.chatId).toBe(789012);
            (0, vitest_1.expect)(result.inviteLink).toBe('https://t.me/+xyz');
        });
        (0, vitest_1.it)('returns chatId without inviteLink if export fails', async () => {
            const client = createClient();
            await connectClient(client);
            const mockChat = { id: { valueOf: () => 111222 } };
            mockInvoke
                .mockResolvedValueOnce({ chats: [mockChat] }) // CreateChat
                .mockRejectedValueOnce(new Error('Export failed')); // ExportChatInvite fails
            const result = await client.createGroup('Group No Link');
            (0, vitest_1.expect)(result.chatId).toBe(111222);
            (0, vitest_1.expect)(result.inviteLink).toBeUndefined();
        });
        (0, vitest_1.it)('throws if no chat returned from API', async () => {
            const client = createClient();
            await connectClient(client);
            mockInvoke.mockResolvedValueOnce({ chats: [] });
            await (0, vitest_1.expect)(client.createGroup('Empty Group')).rejects.toThrow('Failed to create group: no chat returned');
        });
    });
    (0, vitest_1.describe)('createChannel', () => {
        (0, vitest_1.it)('throws if not connected', async () => {
            const client = createClient();
            await (0, vitest_1.expect)(client.createChannel('Test Channel')).rejects.toThrow('Userbot not connected');
        });
        (0, vitest_1.it)('creates a broadcast channel via channels.CreateChannel', async () => {
            const client = createClient();
            await connectClient(client);
            const mockChannel = { id: { valueOf: () => 555666 } };
            mockInvoke
                .mockResolvedValueOnce({ chats: [mockChannel] }) // CreateChannel
                .mockResolvedValueOnce(Object.assign(Object.create(index_js_1.Api.ChatInviteExported.prototype), { link: 'https://t.me/+chan' }));
            const result = await client.createChannel('Test Channel', 'A test channel');
            (0, vitest_1.expect)(result.chatId).toBe(555666);
            (0, vitest_1.expect)(result.inviteLink).toBe('https://t.me/+chan');
        });
        (0, vitest_1.it)('returns chatId without inviteLink if export fails', async () => {
            const client = createClient();
            await connectClient(client);
            const mockChannel = { id: { valueOf: () => 777888 } };
            mockInvoke
                .mockResolvedValueOnce({ chats: [mockChannel] })
                .mockRejectedValueOnce(new Error('Export failed'));
            const result = await client.createChannel('Channel No Link');
            (0, vitest_1.expect)(result.chatId).toBe(777888);
            (0, vitest_1.expect)(result.inviteLink).toBeUndefined();
        });
        (0, vitest_1.it)('throws if no channel returned from API', async () => {
            const client = createClient();
            await connectClient(client);
            mockInvoke.mockResolvedValueOnce({ chats: [] });
            await (0, vitest_1.expect)(client.createChannel('Empty Channel')).rejects.toThrow('Failed to create channel: no chat returned');
        });
    });
    (0, vitest_1.describe)('sendMessage', () => {
        (0, vitest_1.it)('throws if not connected', async () => {
            const client = createClient();
            await (0, vitest_1.expect)(client.sendMessage(123, 'hello')).rejects.toThrow('Userbot not connected');
        });
        (0, vitest_1.it)('sends text-only message via GramJS', async () => {
            const client = createClient();
            await connectClient(client);
            const mockEntity = { id: 123 };
            const mockInputPeer = { className: 'InputPeerUser' };
            mockGetEntity.mockResolvedValueOnce(mockEntity);
            mockGetInputEntity.mockResolvedValueOnce(mockInputPeer);
            mockSendMessage.mockResolvedValueOnce(undefined);
            await client.sendMessage(123, 'Hello world');
            (0, vitest_1.expect)(mockSendMessage).toHaveBeenCalledWith(mockInputPeer, { message: 'Hello world' });
        });
        (0, vitest_1.it)('sends message with image when imageUrl is provided', async () => {
            const client = createClient();
            await connectClient(client);
            const mockEntity = { id: 456 };
            const mockInputPeer = { className: 'InputPeerChannel' };
            mockGetEntity.mockResolvedValueOnce(mockEntity);
            mockGetInputEntity.mockResolvedValueOnce(mockInputPeer);
            const mockBuffer = new ArrayBuffer(8);
            const mockResponse = {
                ok: true,
                arrayBuffer: () => Promise.resolve(mockBuffer),
            };
            vitest_1.vi.stubGlobal('fetch', vitest_1.vi.fn().mockResolvedValueOnce(mockResponse));
            mockSendFile.mockResolvedValueOnce(undefined);
            await client.sendMessage(456, 'Check this out', 'https://example.com/image.jpg');
            (0, vitest_1.expect)(mockSendFile).toHaveBeenCalledTimes(1);
            const callArgs = mockSendFile.mock.calls[0];
            (0, vitest_1.expect)(callArgs[0]).toEqual(mockInputPeer);
            (0, vitest_1.expect)(callArgs[1]).toHaveProperty('caption', 'Check this out');
            vitest_1.vi.unstubAllGlobals();
        });
        (0, vitest_1.it)('falls back to text when image fetch fails', async () => {
            const client = createClient();
            await connectClient(client);
            const mockEntity = { id: 789 };
            const mockInputPeer = { className: 'InputPeerUser' };
            mockGetEntity.mockResolvedValueOnce(mockEntity);
            mockGetInputEntity.mockResolvedValueOnce(mockInputPeer);
            vitest_1.vi.stubGlobal('fetch', vitest_1.vi.fn().mockResolvedValueOnce({ ok: false, status: 404 }));
            mockSendMessage.mockResolvedValueOnce(undefined);
            await client.sendMessage(789, 'Fallback text', 'https://example.com/bad.jpg');
            (0, vitest_1.expect)(mockSendMessage).toHaveBeenCalledWith(mockInputPeer, { message: 'Fallback text' });
            vitest_1.vi.unstubAllGlobals();
        });
    });
});
//# sourceMappingURL=client.test.js.map