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

import { TypeOrmPenaltyRepository, TypeOrmProtestRepository } from './StewardingTypeOrmRepositories';

describe('TypeOrmPenaltyRepository', () => {
  it('findById returns mapped domain when found (DB-free)', async () => {
    const ormEntity = { id: 'p1' };

    const repo = {
      findOne: vi.fn().mockResolvedValue(ormEntity),
      find: vi.fn(),
      save: vi.fn(),
      count: vi.fn(),
      delete: vi.fn(),
    };

    const mapper = {
      toDomain: vi.fn().mockReturnValue({ id: 'domain' }),
      toOrmEntity: vi.fn(),
    };

    const penaltyRepo = new TypeOrmPenaltyRepository(repo as any, mapper as any);

    const result = await penaltyRepo.findById('p1');

    expect(repo.findOne).toHaveBeenCalledWith({ where: { id: 'p1' } });
    expect(mapper.toDomain).toHaveBeenCalledWith(ormEntity);
    expect(result).toEqual({ id: 'domain' });
  });

  it('create uses mapper.toOrmEntity + repo.save', async () => {
    const repo = {
      save: vi.fn().mockResolvedValue(undefined),
    };

    const mapper = {
      toOrmEntity: vi.fn().mockReturnValue({ id: 'p1-orm' }),
    };

    const penaltyRepo = new TypeOrmPenaltyRepository(repo as any, mapper as any);

    await penaltyRepo.create({ id: 'p1' } as any);

    expect(mapper.toOrmEntity).toHaveBeenCalled();
    expect(repo.save).toHaveBeenCalledWith({ id: 'p1-orm' });
  });
});

describe('TypeOrmProtestRepository', () => {
  it('findPending uses injected repo + mapper (DB-free)', async () => {
    const entities = [{ id: 'r1' }, { id: 'r2' }];

    const repo = {
      find: vi.fn().mockResolvedValue(entities),
      findOne: vi.fn(),
      save: vi.fn(),
      count: vi.fn(),
    };

    const mapper = {
      toDomain: vi.fn().mockImplementation((e: any) => ({ id: `domain-${e.id}` })),
      toOrmEntity: vi.fn(),
    };

    const protestRepo = new TypeOrmProtestRepository(repo as any, mapper as any);

    const results = await protestRepo.findPending();

    expect(repo.find).toHaveBeenCalledWith({ where: { status: 'pending' } });
    expect(mapper.toDomain).toHaveBeenCalledTimes(2);
    expect(results).toEqual([{ id: 'domain-r1' }, { id: 'domain-r2' }]);
  });
});