import { describe, it, expect, beforeEach } from 'vitest';
import { DrizzleLogChunkRepository } from './log-chunk.js';
import { createTestDatabase } from './test-helpers.js';
import type { DrizzleDatabase } from '../../index.js';

describe('DrizzleLogChunkRepository', () => {
  let db: DrizzleDatabase;
  let repo: DrizzleLogChunkRepository;
  const testAgentId = 'agent-test-001';

  beforeEach(() => {
    db = createTestDatabase();
    repo = new DrizzleLogChunkRepository(db);
  });

  it('AskUserQuestion chunk — questionsCount upserted correctly', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'tool_use', name: 'AskUserQuestion', input: { questions: [{}, {}] } }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([{
      agentId: testAgentId,
      questionsCount: 2,
      subagentsCount: 0,
      compactionsCount: 0,
    }]);
  });

  it('Agent tool chunk — subagentsCount incremented', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'tool_use', name: 'Agent' }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([{
      agentId: testAgentId,
      questionsCount: 0,
      subagentsCount: 1,
      compactionsCount: 0,
    }]);
  });

  it('Compaction event — compactionsCount incremented', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'system', subtype: 'init', source: 'compact' }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([{
      agentId: testAgentId,
      questionsCount: 0,
      subagentsCount: 0,
      compactionsCount: 1,
    }]);
  });

  it('Irrelevant chunk type — no metrics row created', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'text', text: 'hello' }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([]);
  });

  it('Malformed JSON chunk — chunk persisted, metrics row absent', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: 'not-valid-json',
    });
    const chunks = await repo.findByAgentId(testAgentId);
    expect(chunks).toHaveLength(1);
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([]);
  });

  it('Multiple inserts, same agent — counts accumulate additively', async () => {
    // 3 Agent tool chunks
    for (let i = 0; i < 3; i++) {
      await repo.insertChunk({
        agentId: testAgentId,
        agentName: 'test-agent',
        sessionNumber: 1,
        content: JSON.stringify({ type: 'tool_use', name: 'Agent' }),
      });
    }
    // 1 AskUserQuestion with 2 questions
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'tool_use', name: 'AskUserQuestion', input: { questions: [{}, {}] } }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([{
      agentId: testAgentId,
      questionsCount: 2,
      subagentsCount: 3,
      compactionsCount: 0,
    }]);
  });

  it('findMetricsByAgentIds with empty array — returns []', async () => {
    const metrics = await repo.findMetricsByAgentIds([]);
    expect(metrics).toEqual([]);
  });

  it('findMetricsByAgentIds with agentId that has no metrics row — returns []', async () => {
    await repo.insertChunk({
      agentId: testAgentId,
      agentName: 'test-agent',
      sessionNumber: 1,
      content: JSON.stringify({ type: 'text', text: 'hello' }),
    });
    const metrics = await repo.findMetricsByAgentIds([testAgentId]);
    expect(metrics).toEqual([]);
  });
});
