import { EngagementEvent } from '@core/analytics/domain/entities/EngagementEvent';
import type { Logger } from '@core/shared/domain/Logger';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { InMemoryEngagementRepository } from './InMemoryEngagementRepository';

describe('InMemoryEngagementRepository', () => {
  let repository: InMemoryEngagementRepository;
  let mockLogger: Logger;

  beforeEach(() => {
    mockLogger = {
      debug: vi.fn(),
      info: vi.fn(),
      warn: vi.fn(),
      error: vi.fn(),
    } as unknown as Logger;

    repository = new InMemoryEngagementRepository(mockLogger);
    repository.clear();
  });

  it('initializes with a logger', () => {
    expect(repository).toBeDefined();
    expect(mockLogger.info).toHaveBeenCalledWith('InMemoryEngagementRepository initialized.');
  });

  it('saves and queries engagement events', async () => {
    const now = new Date('2025-01-01T12:00:00.000Z');
    const event1 = EngagementEvent.create({
      id: 'e1',
      action: 'click_sponsor_logo',
      entityType: 'league',
      entityId: 'league-1',
      actorType: 'driver',
      actorId: 'driver-1',
      sessionId: 's1',
      timestamp: now,
    });
    const event2 = EngagementEvent.create({
      id: 'e2',
      action: 'view_schedule',
      entityType: 'league',
      entityId: 'league-1',
      actorType: 'anonymous',
      sessionId: 's2',
      timestamp: new Date(now.getTime() + 1000),
    });

    await repository.save(event1);
    await repository.save(event2);

    expect((await repository.findById('e1'))?.id).toBe('e1');
    expect((await repository.findByEntityId('league', 'league-1')).length).toBe(2);
    expect((await repository.findByAction('view_schedule')).map(e => e.id)).toEqual(['e2']);

    const inRange = await repository.findByDateRange(
      new Date('2025-01-01T00:00:00.000Z'),
      new Date('2025-01-01T23:59:59.999Z'),
    );
    expect(inRange.length).toBe(2);

    const clicks = await repository.getSponsorClicksForEntity('league-1');
    expect(clicks).toBe(1);

    const counted = await repository.countByAction('view_schedule', 'league-1');
    expect(counted).toBe(1);
  });

  it('seeds events', async () => {
    const e = EngagementEvent.create({
      id: 'seed-1',
      action: 'view_schedule',
      entityType: 'league',
      entityId: 'league-2',
      actorType: 'anonymous',
      sessionId: 's3',
    });

    repository.seed([e]);

    expect((await repository.findById('seed-1'))?.id).toBe('seed-1');
  });
});
