import { describe, it, expect, beforeEach } from 'vitest';
import { MemoryEventStore } from './memory-store.js';
import type { StoredEvent } from './types.js';

function makeEvent(overrides?: Partial<StoredEvent>): StoredEvent {
  return {
    id: crypto.randomUUID(),
    type: 'test.event',
    userId: 'u1',
    productId: 'testprod',
    timestamp: new Date().toISOString(),
    payload: {},
    ...overrides,
  };
}

describe('MemoryEventStore', () => {
  let store: MemoryEventStore;

  beforeEach(() => {
    store = new MemoryEventStore({ maxEvents: 100 });
  });

  it('appends and retrieves events', async () => {
    await store.append(makeEvent());
    expect(await store.count()).toBe(1);
    const recent = await store.recent();
    expect(recent).toHaveLength(1);
  });

  it('caps at maxEvents', async () => {
    for (let i = 0; i < 120; i++) {
      await store.append(makeEvent({ id: `e${i}` }));
    }
    expect(await store.count()).toBe(100);
  });

  it('queries by userId', async () => {
    await store.append(makeEvent({ userId: 'u1' }));
    await store.append(makeEvent({ userId: 'u2' }));
    await store.append(makeEvent({ userId: 'u1' }));
    const results = await store.query({ userId: 'u1' });
    expect(results).toHaveLength(2);
  });

  it('queries by type', async () => {
    await store.append(makeEvent({ type: 'task.created' }));
    await store.append(makeEvent({ type: 'schedule.generated' }));
    await store.append(makeEvent({ type: 'task.created' }));
    const results = await store.query({ type: 'task.created' });
    expect(results).toHaveLength(2);
  });

  it('queries with time range', async () => {
    await store.append(makeEvent({ timestamp: '2026-01-01T00:00:00Z' }));
    await store.append(makeEvent({ timestamp: '2026-03-01T00:00:00Z' }));
    await store.append(makeEvent({ timestamp: '2026-06-01T00:00:00Z' }));
    const results = await store.query({
      after: '2026-02-01T00:00:00Z',
      before: '2026-04-01T00:00:00Z',
    });
    expect(results).toHaveLength(1);
  });

  it('queries with limit', async () => {
    for (let i = 0; i < 10; i++) {
      await store.append(makeEvent());
    }
    const results = await store.query({ limit: 3 });
    expect(results).toHaveLength(3);
  });

  it('clears all events', async () => {
    await store.append(makeEvent());
    await store.append(makeEvent());
    await store.clear();
    expect(await store.count()).toBe(0);
  });

  it('recent returns last N events', async () => {
    for (let i = 0; i < 10; i++) {
      await store.append(makeEvent({ id: `e${i}` }));
    }
    const recent = await store.recent(3);
    expect(recent).toHaveLength(3);
    expect(recent[0].id).toBe('e7');
  });
});
