import { describe, it, expect, beforeEach } from 'vitest';
import Database from 'better-sqlite3';
import { createConversation, getActiveConversation, getOrCreateConversation, insertMessage, getMessages, getConversations, generateId, } from '../conversation.js';
function createTestDb() {
    const db = new Database(':memory:');
    db.pragma('journal_mode = WAL');
    db.exec(`
    CREATE TABLE IF NOT EXISTS conversations (
      id TEXT PRIMARY KEY,
      squad_name TEXT NOT NULL,
      created_at TEXT NOT NULL
    );
    CREATE TABLE IF NOT EXISTS chat_messages (
      id TEXT PRIMARY KEY,
      conversation_id TEXT NOT NULL REFERENCES conversations(id),
      role TEXT NOT NULL,
      content TEXT NOT NULL,
      agent_id TEXT,
      agent_name TEXT,
      created_at TEXT NOT NULL
    );
  `);
    return db;
}
describe('conversation module', () => {
    let db;
    beforeEach(() => {
        db = createTestDb();
    });
    describe('generateId', () => {
        it('should generate a timestamp-prefixed id', () => {
            const id = generateId();
            expect(id).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z-[a-f0-9]+$/);
        });
        it('should generate unique ids', () => {
            const ids = new Set(Array.from({ length: 100 }, () => generateId()));
            expect(ids.size).toBe(100);
        });
        it('should be time-sortable', () => {
            const id1 = generateId();
            const id2 = `2099-01-01T00:00:00.000Z-ffffff`;
            expect(id1 < id2).toBe(true);
        });
    });
    describe('createConversation', () => {
        it('should create and return a conversation', () => {
            const conv = createConversation(db, 'content-team');
            expect(conv.squad_name).toBe('content-team');
            expect(conv.id).toMatch(/^\d{4}-/);
            expect(conv.created_at).toBeDefined();
        });
    });
    describe('getActiveConversation', () => {
        it('should return null when no conversations exist', () => {
            const conv = getActiveConversation(db, 'content-team');
            expect(conv).toBeNull();
        });
        it('should return the newest conversation', () => {
            const c1 = createConversation(db, 'content-team');
            db.prepare('INSERT INTO conversations (id, squad_name, created_at) VALUES (?, ?, ?)').run('2099-12-31T23:59:59.999Z-zzz', 'content-team', '2099-12-31T23:59:59.999Z');
            const active = getActiveConversation(db, 'content-team');
            expect(active.id).toBe('2099-12-31T23:59:59.999Z-zzz');
        });
    });
    describe('getOrCreateConversation', () => {
        it('should create a new conversation if none exists', () => {
            const result = getOrCreateConversation(db, 'content-team');
            expect(result.conversation.squad_name).toBe('content-team');
            expect(result.created).toBe(true);
        });
        it('should return existing conversation if one exists', () => {
            const first = createConversation(db, 'content-team');
            const result = getOrCreateConversation(db, 'content-team');
            expect(result.conversation.id).toBe(first.id);
            expect(result.created).toBe(false);
        });
    });
    describe('insertMessage', () => {
        it('should insert a user message', () => {
            const conv = createConversation(db, 'content-team');
            const msg = insertMessage(db, {
                conversationId: conv.id,
                role: 'user',
                content: 'Hello',
            });
            expect(msg.id).toMatch(/^\d{4}-/);
            expect(msg.role).toBe('user');
            expect(msg.content).toBe('Hello');
            expect(msg.agent_id).toBeNull();
        });
        it('should insert an assistant message', () => {
            const conv = createConversation(db, 'content-team');
            const msg = insertMessage(db, {
                conversationId: conv.id,
                role: 'assistant',
                content: 'Hi there!',
            });
            expect(msg.role).toBe('assistant');
        });
        it('should insert an agent_dm message with agent metadata', () => {
            const conv = createConversation(db, 'content-team');
            const msg = insertMessage(db, {
                conversationId: conv.id,
                role: 'agent_dm',
                content: 'Found 5 topics',
                agentId: 'researcher',
                agentName: 'Researcher',
            });
            expect(msg.role).toBe('agent_dm');
            expect(msg.agent_id).toBe('researcher');
            expect(msg.agent_name).toBe('Researcher');
        });
    });
    describe('getMessages', () => {
        it('should return messages oldest-first', () => {
            const conv = createConversation(db, 'content-team');
            // Use explicit IDs to guarantee ordering
            db.prepare('INSERT INTO chat_messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)').run('2026-03-13T10:00:01.000Z-aaa', conv.id, 'user', 'First', '2026-03-13T10:00:01.000Z');
            db.prepare('INSERT INTO chat_messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)').run('2026-03-13T10:00:02.000Z-bbb', conv.id, 'assistant', 'Second', '2026-03-13T10:00:02.000Z');
            db.prepare('INSERT INTO chat_messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)').run('2026-03-13T10:00:03.000Z-ccc', conv.id, 'user', 'Third', '2026-03-13T10:00:03.000Z');
            const result = getMessages(db, conv.id, { limit: 50 });
            expect(result.data).toHaveLength(3);
            expect(result.data[0].content).toBe('First');
            expect(result.data[2].content).toBe('Third');
        });
        it('should paginate with cursor', () => {
            const conv = createConversation(db, 'content-team');
            // Use explicit IDs to guarantee ordering
            for (let i = 0; i < 5; i++) {
                const ts = `2026-03-13T10:00:0${i}.000Z`;
                db.prepare('INSERT INTO chat_messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)').run(`${ts}-m${i}`, conv.id, 'user', `msg-${i}`, ts);
            }
            const page1 = getMessages(db, conv.id, { limit: 2 });
            expect(page1.data).toHaveLength(2);
            expect(page1.nextCursor).toBeDefined();
            const page2 = getMessages(db, conv.id, { limit: 2, cursor: page1.nextCursor });
            expect(page2.data).toHaveLength(2);
            expect(page2.data[0].content).toBe('msg-2');
        });
        it('should return null nextCursor on last page', () => {
            const conv = createConversation(db, 'content-team');
            insertMessage(db, { conversationId: conv.id, role: 'user', content: 'only' });
            const result = getMessages(db, conv.id, { limit: 50 });
            expect(result.nextCursor).toBeNull();
        });
    });
    describe('getConversations', () => {
        it('should return conversations newest-first', () => {
            createConversation(db, 'content-team');
            db.prepare('INSERT INTO conversations (id, squad_name, created_at) VALUES (?, ?, ?)').run('2099-12-31T23:59:59.999Z-zzz', 'content-team', '2099-12-31T23:59:59.999Z');
            const result = getConversations(db, 'content-team', { limit: 20 });
            expect(result.data).toHaveLength(2);
            expect(result.data[0].id).toBe('2099-12-31T23:59:59.999Z-zzz');
        });
        it('should paginate with cursor (newest-first, so cursor uses < comparison)', () => {
            for (let i = 0; i < 5; i++) {
                const ts = `2026-03-13T10:0${i}:00.000Z`;
                db.prepare('INSERT INTO conversations (id, squad_name, created_at) VALUES (?, ?, ?)').run(`${ts}-c${i}`, 'content-team', ts);
            }
            const page1 = getConversations(db, 'content-team', { limit: 2 });
            expect(page1.data).toHaveLength(2);
            expect(page1.nextCursor).toBeDefined();
            const page2 = getConversations(db, 'content-team', { limit: 2, cursor: page1.nextCursor });
            expect(page2.data).toHaveLength(2);
        });
    });
});
//# sourceMappingURL=conversation.test.js.map