package de.szut.casino.coinflip;

import de.szut.casino.shared.service.BalanceService;
import de.szut.casino.user.UserEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.math.BigDecimal;
import java.util.Random;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

class CoinflipServiceTest {

    @Mock
    private BalanceService balanceService;

    @Mock
    private Random random;

    @InjectMocks
    private CoinflipService coinflipService;

    private UserEntity user;
    private CoinflipDto coinflipDto;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
        user = new UserEntity();
        user.setBalance(BigDecimal.valueOf(100));
        coinflipDto = new CoinflipDto(BigDecimal.valueOf(10), CoinSide.HEAD);
    }

    @Test
    void testPlay_userWins() {
        when(random.nextBoolean()).thenReturn(true);

        CoinflipResult result = coinflipService.play(user, coinflipDto);

        assertTrue(result.isWin());
        assertEquals(BigDecimal.valueOf(20), result.getPayout());
        assertEquals(CoinSide.HEAD, result.getCoinSide());
        verify(balanceService, times(1)).subtractFunds(user, BigDecimal.valueOf(10));
        verify(balanceService, times(1)).addFunds(user, BigDecimal.valueOf(20));
    }

    @Test
    void testPlay_userLoses() {
        when(random.nextBoolean()).thenReturn(false);

        CoinflipResult result = coinflipService.play(user, coinflipDto);

        assertFalse(result.isWin());
        assertEquals(BigDecimal.ZERO, result.getPayout());
        assertEquals(CoinSide.TAILS, result.getCoinSide());
        verify(balanceService, times(1)).subtractFunds(user, BigDecimal.valueOf(10));
        verify(balanceService, never()).addFunds(any(), any());
    }
}
