import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { Logger } from '@core/shared/application';
import type { UserRating } from '@core/identity';
import { InMemoryUserRatingRepository } from './InMemoryUserRatingRepository';

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

  const rating = (userId: string, driverValue: number, trustValue: number, canSteward: boolean): UserRating => {
    return {
      userId,
      driver: { sampleSize: 10, value: driverValue },
      trust: { sampleSize: 5, value: trustValue },
      canBeSteward: () => canSteward,
      getDriverTier: () => (driverValue >= 2400 ? 'elite' : 'rookie'),
    } as unknown as UserRating;
  };

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

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

  it('saves and finds ratings', async () => {
    await repository.save(rating('u1', 2300, 50, false));
    await repository.save(rating('u2', 2500, 70, true));

    expect((await repository.findByUserId('u1'))?.userId).toBe('u1');
    expect((await repository.findByUserIds(['u1', 'u2'])).length).toBe(2);

    const topDrivers = await repository.getTopDrivers(1);
    expect(topDrivers[0]?.userId).toBe('u2');

    const topTrusted = await repository.getTopTrusted(1);
    expect(topTrusted[0]?.userId).toBe('u2');

    const stewards = await repository.getEligibleStewards();
    expect(stewards.map(r => r.userId)).toEqual(['u2']);

    const elite = await repository.findByDriverTier('elite');
    expect(elite.map(r => r.userId)).toEqual(['u2']);
  });

  it('deletes ratings', async () => {
    await repository.save(rating('u3', 2200, 10, false));
    await repository.delete('u3');
    expect(await repository.findByUserId('u3')).toBeNull();
  });
});
