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

import cz.muni.fi.pa165.soccermanager.dto.request.CreatePlayerRequest;
import cz.muni.fi.pa165.soccermanager.dto.request.UpdatePlayerDto;
import cz.muni.fi.pa165.soccermanager.factory.PlayerFactory;
import cz.muni.fi.pa165.soccermanager.entity.Player;
import cz.muni.fi.pa165.soccermanager.entity.Team;
import cz.muni.fi.pa165.soccermanager.enums.Nation;
import cz.muni.fi.pa165.soccermanager.enums.PlayerState;
import cz.muni.fi.pa165.soccermanager.enums.Position;
import org.junit.jupiter.api.Assertions;
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 java.util.List;

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

@ExtendWith(MockitoExtension.class)
public class PlayerMapperTest {

    @Mock
    private PlayerFactory playerFactory;

    @InjectMocks
    private PlayerMapperImpl playerMapper;

    @ParameterizedTest
    @NullSource
    public void mapNullTest(Player player) {
        assertNull(playerMapper.map(player));
    }

    @ParameterizedTest
    @NullSource
    public void mapNullTest(List<Player> players) {
        assertNull(playerMapper.map(players));
    }

    @Test
    public void mapDTOHappy() {
        final var dto = new CreatePlayerRequest();
        dto.setBirthDate(LocalDate.of(1, 1, 1));
        dto.setHeight(100.);
        dto.setWeight(180.);
        dto.setDressNumber(99);
        dto.setName("Rooney");
        dto.setNation(Nation.UNITED_KINGDOM);
        dto.setPosition(Position.MIDFIELDER);
        dto.setState(PlayerState.ACTIVE);

        when(playerFactory.prepare(any(CreatePlayerRequest.class))).thenReturn(new Player());
        final var res = playerMapper.map(dto);

        assertEquals(res.getBirthDate(), dto.getBirthDate());
        assertEquals(res.getName(), dto.getName());
        assertEquals(res.getHeight(), dto.getHeight());
        assertEquals(res.getWeight(), dto.getWeight());
        assertEquals(res.getDressNumber(), dto.getDressNumber());
        assertEquals(res.getName(), dto.getName());
        assertEquals(res.getNation(), dto.getNation());
        assertEquals(res.getPosition(), dto.getPosition());
        assertEquals(res.getState(), dto.getState());
    }

    @Test
    public void mapSourceHappy() {
        final var player = new Player();
        player.setBirthDate(LocalDate.of(1, 1, 1));
        player.setHeight(100.);
        player.setWeight(180.);
        player.setDressNumber(99);
        player.setName("Rooney");
        player.setNation(Nation.UNITED_KINGDOM);
        player.setPosition(Position.MIDFIELDER);
        player.setState(PlayerState.ACTIVE);
        player.setTeam(new Team());

        final var res = playerMapper.map(player);

        Assertions.assertEquals(res.getDressNumber(), player.getDressNumber());
        Assertions.assertEquals(res.getPosition(), player.getPosition());
        Assertions.assertEquals(res.getState(), player.getState());
    }

    @Test
    public void mapSourceListHappy() {
        final var player = new Player();
        player.setBirthDate(LocalDate.of(1, 1, 1));
        player.setHeight(100.);
        player.setWeight(180.);
        player.setDressNumber(99);
        player.setName("Rooney");
        player.setNation(Nation.UNITED_KINGDOM);
        player.setPosition(Position.MIDFIELDER);
        player.setState(PlayerState.ACTIVE);
        player.setTeam(new Team());

        final var list = List.of(player);

        final var resList = playerMapper.map(list);
        assertEquals(1, resList.size());

        final var res = resList.get(0);
        Assertions.assertEquals(res.getDressNumber(), player.getDressNumber());
        Assertions.assertEquals(res.getPosition(), player.getPosition());
        Assertions.assertEquals(res.getState(), player.getState());
    }

    @Test
    public void updateMapTest() {
        final var player = new Player();
        player.setBirthDate(LocalDate.of(1, 1, 1));
        player.setHeight(100.);
        player.setWeight(180.);
        player.setDressNumber(99);
        player.setName("Rooney");
        player.setNation(Nation.UNITED_KINGDOM);
        player.setPosition(Position.MIDFIELDER);
        player.setState(PlayerState.ACTIVE);
        player.setTeam(new Team());

        final var dto = new UpdatePlayerDto();
        dto.setName("Joe");
        dto.setDressNumber(7);
        dto.setPosition(Position.FORWARD);
        dto.setState(PlayerState.INJURED);

        playerMapper.mapOnUpdate(player, dto);

        assertEquals(dto.getDressNumber(), player.getDressNumber());
        assertEquals(dto.getPosition(), player.getPosition());
        assertEquals(dto.getState(), player.getState());
    }
}
