import { describe, it, expect } from 'vitest';
import { LeagueWallet } from './LeagueWallet';
import { Money } from '../value-objects/Money';

describe('LeagueWallet', () => {
  it('should create a league wallet', () => {
    const balance = Money.create(10000, 'USD'); // $100
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    expect(wallet.id.toString()).toBe('wallet1');
    expect(wallet.leagueId.toString()).toBe('league1');
    expect(wallet.getBalance().equals(balance)).toBe(true);
    expect(wallet.getTransactionIds()).toEqual([]);
  });

  it('should throw on invalid id', () => {
    const balance = Money.create(10000, 'USD');
    expect(() => LeagueWallet.create({
      id: '',
      leagueId: 'league1',
      balance,
    })).toThrow('LeagueWallet ID is required');
  });

  it('should throw on invalid leagueId', () => {
    const balance = Money.create(10000, 'USD');
    expect(() => LeagueWallet.create({
      id: 'wallet1',
      leagueId: '',
      balance,
    })).toThrow('LeagueWallet leagueId is required');
  });


  it('should add funds', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const netAmount = Money.create(5000, 'USD'); // $50
    const updated = wallet.addFunds(netAmount, 'tx1');

    expect(updated.getBalance().amount).toBe(15000);
    expect(updated.getTransactionIds()).toEqual(['tx1']);
  });

  it('should throw on add funds with different currency', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const netAmount = Money.create(5000, 'EUR');
    expect(() => wallet.addFunds(netAmount, 'tx1')).toThrow('Cannot add funds with different currency');
  });

  it('should withdraw funds', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const amount = Money.create(5000, 'USD');
    const updated = wallet.withdrawFunds(amount, 'tx1');

    expect(updated.getBalance().amount).toBe(5000);
    expect(updated.getTransactionIds()).toEqual(['tx1']);
  });

  it('should throw on withdraw with insufficient balance', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const amount = Money.create(15000, 'USD');
    expect(() => wallet.withdrawFunds(amount, 'tx1')).toThrow('Insufficient balance for withdrawal');
  });

  it('should throw on withdraw with different currency', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const amount = Money.create(5000, 'EUR');
    expect(() => wallet.withdrawFunds(amount, 'tx1')).toThrow('Cannot withdraw funds with different currency');
  });

  it('should check if can withdraw', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    const amount = Money.create(5000, 'USD');
    expect(wallet.canWithdraw(amount)).toBe(true);

    const largeAmount = Money.create(15000, 'USD');
    expect(wallet.canWithdraw(largeAmount)).toBe(false);

    const exactAmount = Money.create(10000, 'USD');
    expect(wallet.canWithdraw(exactAmount)).toBe(true);

    const differentCurrency = Money.create(5000, 'EUR');
    expect(wallet.canWithdraw(differentCurrency)).toBe(false);
  });

  it('should get balance', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
    });

    expect(wallet.getBalance().equals(balance)).toBe(true);
  });

  it('should get transaction ids', () => {
    const balance = Money.create(10000, 'USD');
    const wallet = LeagueWallet.create({
      id: 'wallet1',
      leagueId: 'league1',
      balance,
      transactionIds: ['tx1', 'tx2'],
    });

    expect(wallet.getTransactionIds()).toEqual(['tx1', 'tx2']);
  });
});