package org.fuseri.modulelanguageschool.user;

import org.fuseri.modulelanguageschool.course.Course;
import org.fuseri.modulelanguageschool.course.Language;
import org.fuseri.modulelanguageschool.course.ProficiencyLevel;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

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


@SpringBootTest
class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    private static final User USER = new User(
            "xnovak", "xnovak@emample.com", "Peter", "Novak", Set.of(), new HashMap<>());
    private static final Course COURSE = new Course("AJ1", 10, Language.ENGLISH, ProficiencyLevel.B2);
    private static final List<Course> COURSE_LIST = List.of(COURSE);
    private static final User USER_WITH_ENROLLED_COURSE = new User(
            "xnovak", "xnovak@emample.com", "Peter", "Novak", Set.of(COURSE), Map.of());

    @Test
    void find() {
        when(userRepository.findById(anyLong())).thenReturn(Optional.of(USER));
        User actualUser = userService.find(anyLong());
        assertEquals(USER, actualUser);
    }

    @Test
    void getEnrolled() {
        Long id = 1L;
        when(userRepository.getEnrolled(anyLong())).thenReturn(COURSE_LIST);
        List<Course> actualCourses = userService.getEnrolled(id);
        assertEquals(COURSE_LIST, actualCourses);
    }

    @Test
    void getFinished() {
        long id = 1L;
        when(userRepository.getFinished(anyLong())).thenReturn(COURSE_LIST);
        List<Course> actualCourses = userService.getFinished(id);
        assertEquals(COURSE_LIST, actualCourses);
    }

    @Test
    void addLanguageProficiency() {
        long id = 1L;
        Language language = Language.ENGLISH;
        ProficiencyLevel proficiencyLevel = ProficiencyLevel.B2;
        when(userRepository.findById(id)).thenReturn(Optional.of(USER));
        when(userRepository.save(any(User.class))).thenReturn(USER_WITH_ENROLLED_COURSE);

        User updatedUser = userService.addLanguageProficiency(id, language, proficiencyLevel);
        assertEquals(USER_WITH_ENROLLED_COURSE, updatedUser);
        verify(userRepository).findById(id);
        verify(userRepository).save(any(User.class));
    }
}