"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const backingStore = new Map();
function key(cId, uId) { return `${cId}:${uId}`; }
vitest_1.vi.mock('../data-store/index.js', () => ({
    dataStore: {
        saveConversationHistory: vitest_1.vi.fn(async (h) => {
            backingStore.set(key(h.characterId, h.telegramUserId), structuredClone(h));
        }),
        getConversationHistory: vitest_1.vi.fn(async (cId, uId) => {
            const v = backingStore.get(key(cId, uId));
            return v ? structuredClone(v) : null;
        }),
        deleteConversation: vitest_1.vi.fn(async (cId, uId) => {
            return backingStore.delete(key(cId, uId));
        }),
    },
}));
vitest_1.vi.mock('../../utils/logger.js', () => ({
    createModuleLogger: () => ({ info: vitest_1.vi.fn(), warn: vitest_1.vi.fn(), error: vitest_1.vi.fn() }),
}));
const history_js_1 = require("./history.js");
const index_js_1 = require("../data-store/index.js");
let manager;
(0, vitest_1.beforeEach)(() => {
    manager = new history_js_1.ConversationManager();
    backingStore.clear();
    vitest_1.vi.mocked(index_js_1.dataStore.saveConversationHistory).mockClear();
    vitest_1.vi.mocked(index_js_1.dataStore.getConversationHistory).mockClear();
    vitest_1.vi.mocked(index_js_1.dataStore.deleteConversation).mockClear();
});
(0, vitest_1.describe)('ConversationManager.addMessage', () => {
    (0, vitest_1.it)('should create new history when none exists', async () => {
        const result = await manager.addMessage('char-1', 100, 'user', 'hello');
        (0, vitest_1.expect)(result.characterId).toBe('char-1');
        (0, vitest_1.expect)(result.telegramUserId).toBe(100);
        (0, vitest_1.expect)(result.messages).toHaveLength(1);
        (0, vitest_1.expect)(result.messages[0].role).toBe('user');
        (0, vitest_1.expect)(result.messages[0].content).toBe('hello');
        (0, vitest_1.expect)(result.totalMessages).toBe(1);
    });
    (0, vitest_1.it)('should append to existing history', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        const result = await manager.addMessage('char-1', 100, 'assistant', 'hi there');
        (0, vitest_1.expect)(result.messages).toHaveLength(2);
        (0, vitest_1.expect)(result.messages[1].role).toBe('assistant');
        (0, vitest_1.expect)(result.totalMessages).toBe(2);
    });
    (0, vitest_1.it)('should assign unique message IDs', async () => {
        await manager.addMessage('char-1', 100, 'user', 'msg1');
        const result = await manager.addMessage('char-1', 100, 'user', 'msg2');
        const ids = result.messages.map(m => m.id);
        (0, vitest_1.expect)(new Set(ids).size).toBe(2);
    });
    (0, vitest_1.it)('should store metadata when provided', async () => {
        const result = await manager.addMessage('char-1', 100, 'assistant', 'want a pic?', { starsPitchMade: true });
        (0, vitest_1.expect)(result.messages[0].metadata?.starsPitchMade).toBe(true);
    });
    (0, vitest_1.it)('should not include metadata key when not provided', async () => {
        const result = await manager.addMessage('char-1', 100, 'user', 'hello');
        (0, vitest_1.expect)(result.messages[0].metadata).toBeUndefined();
    });
    (0, vitest_1.it)('should update lastActivity timestamp', async () => {
        const r1 = await manager.addMessage('char-1', 100, 'user', 'first');
        const t1 = r1.lastActivity;
        await new Promise(r => setTimeout(r, 10));
        const r2 = await manager.addMessage('char-1', 100, 'user', 'second');
        (0, vitest_1.expect)(r2.lastActivity >= t1).toBe(true);
    });
    (0, vitest_1.it)('should call dataStore.saveConversationHistory', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        (0, vitest_1.expect)(index_js_1.dataStore.saveConversationHistory).toHaveBeenCalledTimes(1);
    });
});
(0, vitest_1.describe)('ConversationManager.getHistory', () => {
    (0, vitest_1.it)('should return null when no history exists', async () => {
        const result = await manager.getHistory('char-1', 999);
        (0, vitest_1.expect)(result).toBeNull();
    });
    (0, vitest_1.it)('should return full history', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        await manager.addMessage('char-1', 100, 'assistant', 'hi');
        const result = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(result).not.toBeNull();
        (0, vitest_1.expect)(result.messages).toHaveLength(2);
    });
});
(0, vitest_1.describe)('ConversationManager.getRecentMessages', () => {
    (0, vitest_1.it)('should return empty array when no history exists', async () => {
        const result = await manager.getRecentMessages('char-1', 999);
        (0, vitest_1.expect)(result).toEqual([]);
    });
    (0, vitest_1.it)('should return all messages within the time window', async () => {
        await manager.addMessage('char-1', 100, 'user', 'recent');
        const result = await manager.getRecentMessages('char-1', 100, 72);
        (0, vitest_1.expect)(result).toHaveLength(1);
        (0, vitest_1.expect)(result[0].content).toBe('recent');
    });
    (0, vitest_1.it)('should filter out old messages', async () => {
        await manager.addMessage('char-1', 100, 'user', 'new message');
        const history = await manager.getHistory('char-1', 100);
        // Insert an old message (4 days ago)
        const oldTimestamp = new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString();
        history.messages.unshift({
            id: 'old-msg',
            role: 'user',
            content: 'old message',
            timestamp: oldTimestamp,
        });
        history.totalMessages = history.messages.length;
        await index_js_1.dataStore.saveConversationHistory(history);
        const result = await manager.getRecentMessages('char-1', 100, 72);
        (0, vitest_1.expect)(result).toHaveLength(1);
        (0, vitest_1.expect)(result[0].content).toBe('new message');
    });
    (0, vitest_1.it)('should default to 72 hours', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        const result = await manager.getRecentMessages('char-1', 100);
        (0, vitest_1.expect)(result).toHaveLength(1);
    });
});
(0, vitest_1.describe)('ConversationManager.updateUserInfo', () => {
    (0, vitest_1.it)('should create history if none exists and set user info', async () => {
        await manager.updateUserInfo('char-1', 100, { name: 'Ali' });
        const history = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(history).not.toBeNull();
        (0, vitest_1.expect)(history.userInfo.name).toBe('Ali');
    });
    (0, vitest_1.it)('should update name on existing history', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        await manager.updateUserInfo('char-1', 100, { name: 'Ayşe' });
        const history = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(history.userInfo.name).toBe('Ayşe');
    });
    (0, vitest_1.it)('should merge interests without duplicates', async () => {
        await manager.updateUserInfo('char-1', 100, { interests: ['music', 'art'] });
        await manager.updateUserInfo('char-1', 100, { interests: ['art', 'sports'] });
        const history = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(history.userInfo.interests).toEqual(vitest_1.expect.arrayContaining(['music', 'art', 'sports']));
        (0, vitest_1.expect)(history.userInfo.interests).toHaveLength(3);
    });
    (0, vitest_1.it)('should merge notes without duplicates', async () => {
        await manager.updateUserInfo('char-1', 100, { notes: ['likes cats'] });
        await manager.updateUserInfo('char-1', 100, { notes: ['likes cats', 'works at tech'] });
        const history = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(history.userInfo.notes).toHaveLength(2);
    });
});
(0, vitest_1.describe)('ConversationManager.deleteHistory', () => {
    (0, vitest_1.it)('should delete existing history and return true', async () => {
        await manager.addMessage('char-1', 100, 'user', 'hello');
        const deleted = await manager.deleteHistory('char-1', 100);
        (0, vitest_1.expect)(deleted).toBe(true);
        const result = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(result).toBeNull();
    });
    (0, vitest_1.it)('should return false when no history exists', async () => {
        const deleted = await manager.deleteHistory('char-1', 999);
        (0, vitest_1.expect)(deleted).toBe(false);
    });
});
(0, vitest_1.describe)('Message ordering', () => {
    (0, vitest_1.it)('should keep messages in chronological order', async () => {
        await manager.addMessage('char-1', 100, 'user', 'first');
        await new Promise(r => setTimeout(r, 10));
        await manager.addMessage('char-1', 100, 'assistant', 'second');
        await new Promise(r => setTimeout(r, 10));
        await manager.addMessage('char-1', 100, 'user', 'third');
        const history = await manager.getHistory('char-1', 100);
        const timestamps = history.messages.map(m => m.timestamp);
        for (let i = 1; i < timestamps.length; i++) {
            (0, vitest_1.expect)(timestamps[i] >= timestamps[i - 1]).toBe(true);
        }
    });
});
(0, vitest_1.describe)('Photo message saving', () => {
    (0, vitest_1.it)('should save a photo message with messageType, imagePath fields', async () => {
        const result = await manager.addMessage('char-1', 100, 'user', '[Fotoğraf]', undefined, {
            messageType: 'photo',
            imagePath: '/static/characters/char-1/incoming-photos/photo_123.jpg',
        });
        (0, vitest_1.expect)(result.messages).toHaveLength(1);
        const msg = result.messages[0];
        (0, vitest_1.expect)(msg.messageType).toBe('photo');
        (0, vitest_1.expect)(msg.imagePath).toBe('/static/characters/char-1/incoming-photos/photo_123.jpg');
        (0, vitest_1.expect)(msg.content).toBe('[Fotoğraf]');
        (0, vitest_1.expect)(msg.role).toBe('user');
    });
    (0, vitest_1.it)('should save a text_photo message with all photo fields', async () => {
        const result = await manager.addMessage('char-1', 100, 'user', 'Check this out!', undefined, {
            messageType: 'text_photo',
            imagePath: '/static/characters/char-1/incoming-photos/photo_456.jpg',
            imageUrl: 'https://example.com/photo.jpg',
        });
        const msg = result.messages[0];
        (0, vitest_1.expect)(msg.messageType).toBe('text_photo');
        (0, vitest_1.expect)(msg.imagePath).toBe('/static/characters/char-1/incoming-photos/photo_456.jpg');
        (0, vitest_1.expect)(msg.imageUrl).toBe('https://example.com/photo.jpg');
        (0, vitest_1.expect)(msg.content).toBe('Check this out!');
    });
    (0, vitest_1.it)('should not set photo fields when photoInfo is not provided', async () => {
        const result = await manager.addMessage('char-1', 100, 'user', 'just text');
        const msg = result.messages[0];
        (0, vitest_1.expect)(msg.messageType).toBeUndefined();
        (0, vitest_1.expect)(msg.imagePath).toBeUndefined();
        (0, vitest_1.expect)(msg.imageUrl).toBeUndefined();
    });
    (0, vitest_1.it)('should preserve photo fields on round-trip read', async () => {
        await manager.addMessage('char-1', 100, 'user', 'photo msg', undefined, {
            messageType: 'photo',
            imagePath: '/static/characters/char-1/incoming-photos/test.jpg',
        });
        const history = await manager.getHistory('char-1', 100);
        (0, vitest_1.expect)(history).not.toBeNull();
        const msg = history.messages[0];
        (0, vitest_1.expect)(msg.messageType).toBe('photo');
        (0, vitest_1.expect)(msg.imagePath).toBe('/static/characters/char-1/incoming-photos/test.jpg');
        (0, vitest_1.expect)(msg.role).toBe('user');
        (0, vitest_1.expect)(msg.content).toBe('photo msg');
    });
    (0, vitest_1.it)('should save both metadata and photoInfo together', async () => {
        const result = await manager.addMessage('char-1', 100, 'assistant', '[Fotoğraf gönderildi]', { photoSent: true }, {
            messageType: 'photo',
            imagePath: '/static/characters/char-1/generated-images/gen_789.jpg',
        });
        const msg = result.messages[0];
        (0, vitest_1.expect)(msg.metadata?.photoSent).toBe(true);
        (0, vitest_1.expect)(msg.messageType).toBe('photo');
        (0, vitest_1.expect)(msg.imagePath).toBe('/static/characters/char-1/generated-images/gen_789.jpg');
    });
});
//# sourceMappingURL=history.test.js.map