package org.codiki.images;

import org.codiki.core.entities.dto.ImageDTO;
import org.codiki.core.entities.persistence.Image;
import org.codiki.core.entities.persistence.User;
import org.codiki.core.repositories.ImageRepository;
import org.codiki.core.repositories.UserRepository;
import org.codiki.core.services.FileUploadService;
import org.codiki.core.services.UserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.security.Principal;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

@RunWith(MockitoJUnitRunner.class)
public class ImageServiceTest {

    private ImageService imageService;

    @Mock
    private UserService userService;
    @Mock
    private UserRepository userRepository;
    @Mock
    private FileUploadService fileUploadService;
    @Mock
    private ImageRepository imageRepository;

    @Before
    public void setUp() {
        imageService = new ImageService(userService,
                userRepository,
                fileUploadService,
                imageRepository);
    }

    @Test
    public void getUserImages_should_return_ImageDTO_list() {
        // given
        Principal principal = mock(Principal.class);
        User user = new User();
        user.setId(1L);
        given(userService.getUserByPrincipal(principal)).willReturn(Optional.of(user));

        Image image = new Image();
        image.setId(2L);
        image.setLink("linkValue");
        given(imageRepository.getByUserId(1L)).willReturn(Collections.singletonList(image));

        // when
        List<ImageDTO> result = imageService.getUserImages(principal);

        // then
        assertThat(result).isNotNull().hasSize(1);
        assertThat(result.get(0).getId()).isEqualTo(2L);
        assertThat(result.get(0).getLink()).isEqualTo("linkValue");
    }

    @Test
    public void getUserImages_should_throw_a_NoSuchElementException_if_user_doesnt_exist() {
        // given
        Principal principal = mock(Principal.class);
        given(userService.getUserByPrincipal(principal)).willReturn(Optional.empty());

        // when
        Throwable throwable = catchThrowable(() -> imageService.getUserImages(principal));

        // then
        assertThat(throwable).isNotNull().isExactlyInstanceOf(NoSuchElementException.class);
    }

    @Test
    public void getUserImages_should_return_an_empty_list_if_user_doesnt_have_any_image() {
        // given
        Principal principal = mock(Principal.class);
        User user = new User();
        user.setId(1L);
        given(userService.getUserByPrincipal(principal)).willReturn(Optional.of(user));

        given(imageRepository.getByUserId(1L)).willReturn(Collections.emptyList());

        // when
        List<ImageDTO> result = imageService.getUserImages(principal);

        // then
        assertThat(result).isNotNull().isEmpty();
    }
}
