import { Decimal } from '@prisma/client/runtime/library';
import { WalletService } from './wallet.service';
import { expectAppError } from '../../testing/prisma-mock';

describe('WalletService', () => {
  const tx = {
    $queryRaw: jest.fn(),
    wallet: {
      update: jest.fn(),
    },
    walletTransaction: {
      findUnique: jest.fn(),
      create: jest.fn(),
    },
  };
  const prisma = {
    $transaction: jest.fn(async (fn: (client: typeof tx) => Promise<unknown>) => fn(tx)),
  };

  let service: WalletService;

  beforeEach(() => {
    jest.clearAllMocks();
    service = new WalletService(prisma as never);
    tx.walletTransaction.findUnique.mockResolvedValue(null);
  });

  it('rejects settlement when frozen funds are lower than the stake', async () => {
    tx.$queryRaw.mockResolvedValue([
      {
        id: 1n,
        available_balance: new Decimal(10),
        frozen_balance: new Decimal(40),
        version: 1,
      },
    ]);

    await expect(
      service.settleBet(
        99n,
        new Decimal(50),
        new Decimal(0),
        'BET-LOW-FROZEN',
        'LOSE',
        undefined,
        'settle:BATCH:BET-LOW-FROZEN',
      ),
    ).rejects.toMatchObject(expectAppError('WALLET_FROZEN_INSUFFICIENT'));

    expect(tx.wallet.update).not.toHaveBeenCalled();
    expect(tx.walletTransaction.create).not.toHaveBeenCalled();
  });

  it('lists player-approved deposits in transfer transactions', async () => {
    const listPrisma = {
      walletTransaction: {
        findMany: jest.fn().mockResolvedValue([]),
        count: jest.fn().mockResolvedValue(0),
      },
    };
    const listService = new WalletService(listPrisma as never);

    await listService.listTransferTransactions({});

    expect(listPrisma.walletTransaction.findMany).toHaveBeenCalledWith(
      expect.objectContaining({
        where: expect.objectContaining({
          transactionType: expect.objectContaining({
            in: expect.arrayContaining(['PLAYER_DEPOSIT']),
          }),
        }),
      }),
    );
  });
});
