"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const stars_manager_js_1 = require("./stars-manager.js");
vitest_1.vi.mock('uuid', () => {
    let counter = 0;
    return { v4: () => `uuid-${++counter}` };
});
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(),
    }),
}));
function createMockDataStore() {
    const transactions = new Map();
    return {
        saveStarsTransaction: vitest_1.vi.fn(async (tx) => {
            const list = transactions.get(tx.characterId) ?? [];
            list.push(tx);
            transactions.set(tx.characterId, list);
        }),
        getStarsTransactions: vitest_1.vi.fn(async (characterId) => {
            return [...(transactions.get(characterId) ?? [])];
        }),
        _transactions: transactions,
        _clear: () => transactions.clear(),
    };
}
function createMockBotClient() {
    return {
        answerPreCheckoutQuery: vitest_1.vi.fn(async () => true),
        sendPaidMedia: vitest_1.vi.fn(async () => ({})),
        sendMessage: vitest_1.vi.fn(async () => ({})),
    };
}
const CHAR_ID = 'char-001';
const USER_ID = 12345;
function makePreCheckoutQuery(overrides) {
    return {
        id: 'pchk-1',
        from: { id: USER_ID, is_bot: false, first_name: 'Test' },
        currency: 'XTR',
        total_amount: 50,
        invoice_payload: JSON.stringify({ imageId: 'img_abc' }),
        ...overrides,
    };
}
function makeSuccessfulPayment(overrides) {
    return {
        currency: 'XTR',
        total_amount: 50,
        invoice_payload: JSON.stringify({ imageId: 'img_abc' }),
        telegram_payment_charge_id: 'tg_charge_1',
        provider_payment_charge_id: 'prov_charge_1',
        ...overrides,
    };
}
(0, vitest_1.describe)('StarsManager', () => {
    let manager;
    let mockStore;
    let mockBot;
    (0, vitest_1.beforeEach)(() => {
        vitest_1.vi.clearAllMocks();
        mockStore = createMockDataStore();
        mockBot = createMockBotClient();
        manager = new stars_manager_js_1.StarsManager(mockStore);
    });
    (0, vitest_1.describe)('handlePreCheckout', () => {
        (0, vitest_1.it)('should approve pre-checkout query and create pending transaction', async () => {
            const query = makePreCheckoutQuery();
            await manager.handlePreCheckout(CHAR_ID, query, mockBot);
            (0, vitest_1.expect)(mockBot.answerPreCheckoutQuery).toHaveBeenCalledWith('pchk-1', true);
            (0, vitest_1.expect)(mockStore.saveStarsTransaction).toHaveBeenCalledTimes(1);
            const savedTx = mockStore.saveStarsTransaction.mock.calls[0][0];
            (0, vitest_1.expect)(savedTx.characterId).toBe(CHAR_ID);
            (0, vitest_1.expect)(savedTx.telegramUserId).toBe(USER_ID);
            (0, vitest_1.expect)(savedTx.type).toBe('payment');
            (0, vitest_1.expect)(savedTx.starCount).toBe(50);
            (0, vitest_1.expect)(savedTx.status).toBe('pending');
        });
        (0, vitest_1.it)('should throw if answerPreCheckoutQuery fails', async () => {
            mockBot.answerPreCheckoutQuery.mockRejectedValueOnce(new Error('API error'));
            const query = makePreCheckoutQuery();
            await (0, vitest_1.expect)(manager.handlePreCheckout(CHAR_ID, query, mockBot)).rejects.toThrow('API error');
        });
    });
    (0, vitest_1.describe)('handleSuccessfulPayment', () => {
        (0, vitest_1.it)('should create completed transaction and send paid media', async () => {
            const payment = makeSuccessfulPayment();
            const tx = await manager.handleSuccessfulPayment(CHAR_ID, payment, USER_ID, mockBot);
            (0, vitest_1.expect)(tx.status).toBe('completed');
            (0, vitest_1.expect)(tx.telegramPaymentId).toBe('tg_charge_1');
            (0, vitest_1.expect)(tx.imageId).toBe('img_abc');
            (0, vitest_1.expect)(mockBot.sendPaidMedia).toHaveBeenCalledWith({
                chat_id: USER_ID,
                star_count: 50,
                media: [{ type: 'photo', media: 'img_abc' }],
            });
        });
        (0, vitest_1.it)('should not send paid media when no imageId in payload', async () => {
            const payment = makeSuccessfulPayment({ invoice_payload: 'no-json' });
            const tx = await manager.handleSuccessfulPayment(CHAR_ID, payment, USER_ID, mockBot);
            (0, vitest_1.expect)(tx.status).toBe('completed');
            (0, vitest_1.expect)(mockBot.sendPaidMedia).not.toHaveBeenCalled();
        });
        (0, vitest_1.it)('should parse img_ prefixed payload as imageId', async () => {
            const payment = makeSuccessfulPayment({ invoice_payload: 'img_xyz123' });
            const tx = await manager.handleSuccessfulPayment(CHAR_ID, payment, USER_ID, mockBot);
            (0, vitest_1.expect)(tx.imageId).toBe('img_xyz123');
            (0, vitest_1.expect)(mockBot.sendPaidMedia).toHaveBeenCalled();
        });
        (0, vitest_1.it)('should still complete transaction if sendPaidMedia fails', async () => {
            mockBot.sendPaidMedia.mockRejectedValueOnce(new Error('send failed'));
            const payment = makeSuccessfulPayment();
            const tx = await manager.handleSuccessfulPayment(CHAR_ID, payment, USER_ID, mockBot);
            (0, vitest_1.expect)(tx.status).toBe('completed');
        });
    });
    (0, vitest_1.describe)('handleStarReaction', () => {
        (0, vitest_1.it)('should create a completed reaction transaction', async () => {
            const tx = await manager.handleStarReaction(CHAR_ID, USER_ID, 5);
            (0, vitest_1.expect)(tx.type).toBe('reaction');
            (0, vitest_1.expect)(tx.starCount).toBe(5);
            (0, vitest_1.expect)(tx.status).toBe('completed');
            (0, vitest_1.expect)(tx.characterId).toBe(CHAR_ID);
            (0, vitest_1.expect)(tx.telegramUserId).toBe(USER_ID);
        });
    });
    (0, vitest_1.describe)('publishPaidMedia', () => {
        (0, vitest_1.it)('should call sendPaidMedia on the bot client', async () => {
            await manager.publishPaidMedia(CHAR_ID, '-1001234', 'img_001', 100, mockBot, 'VIP content');
            (0, vitest_1.expect)(mockBot.sendPaidMedia).toHaveBeenCalledWith({
                chat_id: -1001234,
                star_count: 100,
                media: [{ type: 'photo', media: 'img_001' }],
                caption: 'VIP content',
            });
        });
    });
    (0, vitest_1.describe)('getTransactions', () => {
        async function seedTransactions() {
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'payment', starCount: 50, status: 'completed' });
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'reaction', starCount: 5, status: 'completed' });
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: 999, type: 'payment', starCount: 30, status: 'pending' });
        }
        (0, vitest_1.it)('should return all transactions sorted by createdAt descending', async () => {
            await seedTransactions();
            const txs = await manager.getTransactions(CHAR_ID);
            (0, vitest_1.expect)(txs).toHaveLength(3);
            for (let i = 1; i < txs.length; i++) {
                (0, vitest_1.expect)(new Date(txs[i - 1].createdAt).getTime()).toBeGreaterThanOrEqual(new Date(txs[i].createdAt).getTime());
            }
        });
        (0, vitest_1.it)('should filter by type', async () => {
            await seedTransactions();
            const txs = await manager.getTransactions(CHAR_ID, { type: 'reaction' });
            (0, vitest_1.expect)(txs).toHaveLength(1);
            (0, vitest_1.expect)(txs[0].type).toBe('reaction');
        });
        (0, vitest_1.it)('should filter by status', async () => {
            await seedTransactions();
            const txs = await manager.getTransactions(CHAR_ID, { status: 'pending' });
            (0, vitest_1.expect)(txs).toHaveLength(1);
            (0, vitest_1.expect)(txs[0].status).toBe('pending');
        });
        (0, vitest_1.it)('should support limit and offset', async () => {
            await seedTransactions();
            const txs = await manager.getTransactions(CHAR_ID, { limit: 1, offset: 1 });
            (0, vitest_1.expect)(txs).toHaveLength(1);
        });
    });
    (0, vitest_1.describe)('getRevenue', () => {
        (0, vitest_1.it)('should calculate total revenue from completed transactions', async () => {
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'payment', starCount: 100, status: 'completed' });
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'reaction', starCount: 10, status: 'completed' });
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'payment', starCount: 50, status: 'pending' });
            const revenue = await manager.getRevenue(CHAR_ID);
            (0, vitest_1.expect)(revenue.totalStars).toBe(110);
            (0, vitest_1.expect)(revenue.totalTransactions).toBe(2);
            (0, vitest_1.expect)(revenue.byType.payment).toBe(100);
            (0, vitest_1.expect)(revenue.byType.reaction).toBe(10);
        });
        (0, vitest_1.it)('should return zero revenue for character with no transactions', async () => {
            const revenue = await manager.getRevenue('nonexistent');
            (0, vitest_1.expect)(revenue.totalStars).toBe(0);
            (0, vitest_1.expect)(revenue.totalTransactions).toBe(0);
        });
        (0, vitest_1.it)('should filter by daily period', async () => {
            await manager.createTransaction({ characterId: CHAR_ID, telegramUserId: USER_ID, type: 'payment', starCount: 50, status: 'completed' });
            const revenue = await manager.getRevenue(CHAR_ID, 'daily');
            (0, vitest_1.expect)(revenue.totalStars).toBe(50);
        });
    });
    (0, vitest_1.describe)('createTransaction', () => {
        (0, vitest_1.it)('should create a transaction with generated id and timestamp', async () => {
            const tx = await manager.createTransaction({
                characterId: CHAR_ID,
                telegramUserId: USER_ID,
                type: 'payment',
                starCount: 75,
            });
            (0, vitest_1.expect)(tx.id).toBeDefined();
            (0, vitest_1.expect)(tx.createdAt).toBeDefined();
            (0, vitest_1.expect)(tx.status).toBe('pending');
            (0, vitest_1.expect)(tx.starCount).toBe(75);
            (0, vitest_1.expect)(mockStore.saveStarsTransaction).toHaveBeenCalledWith(tx);
        });
        (0, vitest_1.it)('should use provided status when given', async () => {
            const tx = await manager.createTransaction({
                characterId: CHAR_ID,
                telegramUserId: USER_ID,
                type: 'payment',
                starCount: 25,
                status: 'completed',
            });
            (0, vitest_1.expect)(tx.status).toBe('completed');
        });
    });
});
//# sourceMappingURL=stars-manager.test.js.map