package cz.muni.fi.pa165.soccermanager.mapper;

import cz.muni.fi.pa165.soccermanager.dto.MatchDto;
import cz.muni.fi.pa165.soccermanager.dto.MatchScoreDto;
import cz.muni.fi.pa165.soccermanager.dto.request.CreateMatchRequest;
import cz.muni.fi.pa165.soccermanager.dto.request.UpdateMatchDto;
import cz.muni.fi.pa165.soccermanager.factory.MatchFactory;
import cz.muni.fi.pa165.soccermanager.entity.Match;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDate;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

/**
 * @author Stanislav Koshchienko (uco: 506549)
 */
@ExtendWith(MockitoExtension.class)
public class MatchMapperTest {

    private final LocalDate DATE1 = LocalDate.of(2022, 3, 26);
    private final LocalDate DATE2 = LocalDate.of(2022, 6, 18);

    @Mock
    private MatchFactory matchFactory;

    @InjectMocks
    private MatchMapperImpl matchMapper;

    @ParameterizedTest
    @NullSource
    public void mapNullTest(Match match) {
        assertNull(matchMapper.map(match));
    }

    @Test
    public void mapRequestHappy() {
        final var request = new CreateMatchRequest();
        request.setStartDate(DATE1);
        request.setPlayPlace("Brno");

        when(matchFactory.prepare(any(CreateMatchRequest.class))).thenReturn(new Match());

        final var res = matchMapper.map(request);
        assertEquals(res.getStartDate(), request.getStartDate());
        assertEquals(res.getPlayPlace(), request.getPlayPlace());

    }

    @Test
    public void mapSourceHappy() {
        final var match = new Match();
        match.setStartDate(DATE1);
        match.setPlayPlace("Brno");
        match.setDefenderGoals(1);
        match.setChallengerGoals(3);

        final MatchDto res = matchMapper.map(match);
        assertEquals(res.getStartDate(), match.getStartDate());
        assertEquals(res.getPlayPlace(), match.getPlayPlace());
        assertEquals(res.getResult().getChallengerGoals(), 3);
        assertEquals(res.getResult().getDefenderGoals(), 1);
    }


    @Test
    public void updateMapTest() {
        final var match = new Match();
        match.setStartDate(DATE1);
        match.setPlayPlace("Brno");
        match.setDefenderGoals(1);
        match.setChallengerGoals(3);

        final var dto = new UpdateMatchDto();
        dto.setStartDate(DATE2);
        dto.setPlayPlace("Prague");
        dto.setResult(new MatchScoreDto());
        dto.getResult().setDefenderGoals(4);
        dto.getResult().setChallengerGoals(5);

        matchMapper.mapOnUpdate(match, dto);
        assertEquals(dto.getStartDate(), match.getStartDate());
        assertEquals(dto.getPlayPlace(), match.getPlayPlace());
        assertEquals(match.getChallengerGoals(), 5);
        assertEquals(match.getDefenderGoals(), 4);
    }
}
