import type { DataSource } from 'typeorm';
import { describe, expect, it, vi } from 'vitest';

import { TypeOrmRatingEventRepository } from './TypeOrmRatingEventRepository';

describe('TypeOrmRatingEventRepository', () => {
  it('constructor works with injected dependencies', () => {
    const dataSource = {} as unknown as DataSource;
    const repo = new TypeOrmRatingEventRepository(dataSource);
    expect(repo).toBeInstanceOf(TypeOrmRatingEventRepository);
  });

  it('save: works with mocked TypeORM', async () => {
    const save = vi.fn().mockResolvedValue({});
    const dataSource = {
      getRepository: vi.fn().mockReturnValue({ save }),
    } as unknown as DataSource;

    const repo = new TypeOrmRatingEventRepository(dataSource);
    
    // Create a mock event (we're testing the repository wiring, not the mapper)
    const mockEvent = {
      id: { value: 'test-id' },
      userId: 'user-1',
      dimension: { value: 'driving' },
      delta: { value: 5 },
      occurredAt: new Date(),
      createdAt: new Date(),
      source: { type: 'race', id: 'race-1' },
      reason: { code: 'TEST', summary: 'Test', details: {} },
      visibility: { public: true, redactedFields: [] },
      version: 1,
    } as any;

    // Mock the mapper
    vi.doMock('../mappers/RatingEventOrmMapper', () => ({
      RatingEventOrmMapper: {
        toOrmEntity: vi.fn().mockReturnValue({ id: 'test-id' }),
      },
    }));

    const result = await repo.save(mockEvent);
    expect(result).toBe(mockEvent);
    expect(save).toHaveBeenCalled();
  });

  it('findByUserId: returns empty array with mocked DB', async () => {
    const getMany = vi.fn().mockResolvedValue([]);
    const createQueryBuilder = vi.fn().mockReturnValue({
      where: vi.fn().mockReturnThis(),
      orderBy: vi.fn().mockReturnThis(),
      addOrderBy: vi.fn().mockReturnThis(),
      andWhere: vi.fn().mockReturnThis(),
      limit: vi.fn().mockReturnThis(),
      getMany,
    });

    const dataSource = {
      getRepository: vi.fn().mockReturnValue({ createQueryBuilder }),
    } as unknown as DataSource;

    const repo = new TypeOrmRatingEventRepository(dataSource);
    const result = await repo.findByUserId('user-1');

    expect(result).toEqual([]);
    expect(createQueryBuilder).toHaveBeenCalled();
  });

  it('getAllByUserId: works with mocked DB', async () => {
    const getMany = vi.fn().mockResolvedValue([]);
    const createQueryBuilder = vi.fn().mockReturnValue({
      where: vi.fn().mockReturnThis(),
      orderBy: vi.fn().mockReturnThis(),
      addOrderBy: vi.fn().mockReturnThis(),
      getMany,
    });

    const dataSource = {
      getRepository: vi.fn().mockReturnValue({ createQueryBuilder }),
    } as unknown as DataSource;

    const repo = new TypeOrmRatingEventRepository(dataSource);
    const result = await repo.getAllByUserId('user-1');

    expect(result).toEqual([]);
    expect(createQueryBuilder).toHaveBeenCalled();
  });

  it('findByIds: handles empty array', async () => {
    const dataSource = {} as unknown as DataSource;
    const repo = new TypeOrmRatingEventRepository(dataSource);
    const result = await repo.findByIds([]);
    expect(result).toEqual([]);
  });
});