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

import {
    TypeOrmGameRepository,
    TypeOrmLeagueWalletRepository,
    TypeOrmSponsorRepository,
    TypeOrmTransactionRepository,
} from './CommerceTypeOrmRepositories';

describe('TypeOrmGameRepository', () => {
  it('findAll maps entities to domain using injected mapper (DB-free)', async () => {
    const entities = [{ id: 'g1' }, { id: 'g2' }];

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

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

    const gameRepo = new TypeOrmGameRepository(repo as any, mapper as any);

    const games = await gameRepo.findAll();

    expect(repo.find).toHaveBeenCalledTimes(1);
    expect(mapper.toDomain).toHaveBeenCalledTimes(2);
    expect(games).toEqual([{ id: 'domain-g1' }, { id: 'domain-g2' }]);
  });
});

describe('TypeOrmLeagueWalletRepository', () => {
  it('exists returns true when count > 0 (DB-free)', async () => {
    const repo = {
      count: vi.fn().mockResolvedValue(1),
      findOne: vi.fn(),
      save: vi.fn(),
      delete: vi.fn(),
    };

    const mapper = {
      toDomain: vi.fn(),
      toOrmEntity: vi.fn(),
    };

    const walletRepo = new TypeOrmLeagueWalletRepository(repo as any, mapper as any);

    await expect(walletRepo.exists('w1')).resolves.toBe(true);
    expect(repo.count).toHaveBeenCalledWith({ where: { id: 'w1' } });
  });
});

describe('TypeOrmTransactionRepository', () => {
  it('findByWalletId maps entities to domain (DB-free)', async () => {
    const entities = [{ id: 't1' }, { id: 't2' }];

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

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

    const txRepo = new TypeOrmTransactionRepository(repo as any, mapper as any);

    const txs = await txRepo.findByWalletId('wallet-1');

    expect(repo.find).toHaveBeenCalledWith({ where: { walletId: 'wallet-1' } });
    expect(mapper.toDomain).toHaveBeenCalledTimes(2);
    expect(txs).toEqual([{ id: 'domain-t1' }, { id: 'domain-t2' }]);
  });
});

describe('TypeOrmSponsorRepository', () => {
  it('findByEmail queries by contactEmail and maps (DB-free)', async () => {
    const entity = { id: 's1' };

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

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

    const sponsorRepo = new TypeOrmSponsorRepository(repo as any, mapper as any);

    const sponsor = await sponsorRepo.findByEmail('a@example.com');

    expect(repo.findOne).toHaveBeenCalledWith({ where: { contactEmail: 'a@example.com' } });
    expect(mapper.toDomain).toHaveBeenCalledWith(entity);
    expect(sponsor).toEqual({ id: 'domain-s1' });
  });
});