import { describe, it, expect, vi, beforeEach } from 'vitest';
import Database from 'better-sqlite3';
import { ChatHandler } from '../chat-handler';
import { SCHEMA_SQL } from '../../db/schema';
function createTestDb() {
    const db = new Database(':memory:');
    db.pragma('journal_mode = WAL');
    db.exec(SCHEMA_SQL);
    return db;
}
function createMockBridge() {
    return {
        type: 'claude-code',
        send: vi.fn(),
        isActive: vi.fn().mockReturnValue(false),
        kill: vi.fn(),
    };
}
describe('ChatHandler', () => {
    let db;
    let bridge;
    let handler;
    let broadcast;
    beforeEach(() => {
        db = createTestDb();
        bridge = createMockBridge();
        broadcast = vi.fn();
        handler = new ChatHandler({ db, bridge, broadcast, squadsDir: '/tmp/squads', broadcastToAll: vi.fn() });
    });
    describe('handleChatSend', () => {
        it('should create a conversation if none exists', () => {
            handler.handleChatSend('content-team', 'Hello');
            expect(broadcast).toHaveBeenCalledWith('content-team', expect.objectContaining({
                type: 'chat:conversation_created',
                squadName: 'content-team',
                conversationId: expect.any(String),
            }));
        });
        it('should save user message to database', () => {
            handler.handleChatSend('content-team', 'Hello');
            const msgs = db.prepare('SELECT * FROM chat_messages WHERE role = ?').all('user');
            expect(msgs).toHaveLength(1);
            expect(msgs[0].content).toBe('Hello');
        });
        it('should call bridge.send with constructed prompt', () => {
            handler.handleChatSend('content-team', 'Hello');
            expect(bridge.send).toHaveBeenCalledWith(expect.objectContaining({
                prompt: expect.stringContaining('Hello'),
                cwd: '/tmp/squads/content-team',
                squadName: 'content-team',
            }));
        });
        it('should reuse existing conversation', () => {
            handler.handleChatSend('content-team', 'First');
            handler.handleChatSend('content-team', 'Second');
            const createdMessages = broadcast.mock.calls.filter((call) => call[1].type === 'chat:conversation_created');
            expect(createdMessages).toHaveLength(1);
            const msgs = db.prepare('SELECT * FROM chat_messages WHERE role = ?').all('user');
            expect(msgs).toHaveLength(2);
        });
        it('should broadcast chunks from bridge', () => {
            let capturedOnChunk;
            bridge.send.mockImplementation((opts) => {
                capturedOnChunk = opts.onChunk;
            });
            handler.handleChatSend('content-team', 'Hello');
            expect(capturedOnChunk).toBeDefined();
            capturedOnChunk('chunk-1');
            expect(broadcast).toHaveBeenCalledWith('content-team', expect.objectContaining({
                type: 'chat:chunk',
                squadName: 'content-team',
                delta: 'chunk-1',
            }));
        });
        it('should save assistant message and broadcast done on bridge completion', () => {
            let capturedOnDone;
            bridge.send.mockImplementation((opts) => {
                capturedOnDone = opts.onDone;
            });
            handler.handleChatSend('content-team', 'Hello');
            capturedOnDone('Full response text');
            const msgs = db.prepare('SELECT * FROM chat_messages WHERE role = ?').all('assistant');
            expect(msgs).toHaveLength(1);
            expect(msgs[0].content).toBe('Full response text');
            expect(broadcast).toHaveBeenCalledWith('content-team', expect.objectContaining({
                type: 'chat:done',
                squadName: 'content-team',
                messageId: expect.any(String),
            }));
        });
        it('should broadcast error from bridge', () => {
            let capturedOnError;
            bridge.send.mockImplementation((opts) => {
                capturedOnError = opts.onError;
            });
            handler.handleChatSend('content-team', 'Hello');
            capturedOnError({ code: 1, message: 'Exit code 1: error' });
            expect(broadcast).toHaveBeenCalledWith('content-team', expect.objectContaining({
                type: 'chat:error',
                squadName: 'content-team',
                error: 'Exit code 1: error',
            }));
        });
    });
    describe('handleNewConversation', () => {
        it('should create a new conversation and broadcast', () => {
            handler.handleChatSend('content-team', 'Old message');
            broadcast.mockClear();
            handler.handleNewConversation('content-team');
            expect(broadcast).toHaveBeenCalledWith('content-team', expect.objectContaining({
                type: 'chat:conversation_created',
                squadName: 'content-team',
            }));
            const convs = db.prepare('SELECT * FROM conversations WHERE squad_name = ?').all('content-team');
            expect(convs).toHaveLength(2);
        });
    });
    describe('_jarvis squad handling', () => {
        it('uses project root (parent of squadsDir) as cwd for _jarvis', () => {
            handler.handleChatSend('_jarvis', 'Hello');
            const call = bridge.send.mock.calls[0][0];
            expect(call.cwd).toBe('/tmp');
        });
        it('uses squad directory as cwd for regular squads', () => {
            handler.handleChatSend('vendas', 'Hello');
            expect(bridge.send).toHaveBeenCalledWith(expect.objectContaining({
                cwd: '/tmp/squads/vendas',
            }));
        });
        it('uses Jarvis system prompt for _jarvis', () => {
            handler.handleChatSend('_jarvis', 'What squads do I have?');
            const call = bridge.send.mock.calls[0][0];
            expect(call.prompt).toContain('Jarvis');
            expect(call.prompt).not.toContain("assisting with squad '_jarvis'");
        });
        it('uses standard squad prompt for regular squads', () => {
            handler.handleChatSend('vendas', 'Hello');
            const call = bridge.send.mock.calls[0][0];
            expect(call.prompt).toContain("assisting with squad 'vendas'");
        });
    });
});
//# sourceMappingURL=chat-handler.test.js.map