package org.fuseri.modulelanguageschool.lecture;

import org.fuseri.model.dto.lecture.LectureCreateDto;
import org.fuseri.model.dto.lecture.LectureDto;
import org.fuseri.modulelanguageschool.course.Course;
import org.fuseri.modulelanguageschool.course.CourseService;
import org.fuseri.modulelanguageschool.course.Language;
import org.fuseri.modulelanguageschool.course.ProficiencyLevel;
import org.fuseri.modulelanguageschool.user.User;
import org.fuseri.modulelanguageschool.user.UserService;
import org.junit.jupiter.api.Assertions;
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.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when;

@SpringBootTest
final class LectureMapperTest {

    private final LocalDateTime now = LocalDateTime.now();

    private final User lecturer = new User("dolezelt", "dolezel@gmail.com", "Tomáš",
            "Doležel", new HashSet<>(), new HashMap<>());
    private final User student = new User("novakovat", "novakova@gmail.com", "Tereza",
            "Nováková", new HashSet<>(), new HashMap<>());

    private final Course course = new Course("AJ1", 10,
            Language.ENGLISH, ProficiencyLevel.A1);

    private final LectureCreateDto lectureCreateDto = new LectureCreateDto(
            now.plusDays(2),
            now.plusDays(2).plusHours(2),
            "Learning how to spell deprecated",
            10, course.getId());
    private final LectureDto lectureDto = new LectureDto(
            now.plusDays(2),
            now.plusDays(2).plusHours(2),
            "Learning how to spell deprecated",
            10, lecturer.getId(), course.getId(), Collections.emptyList());
    private final Lecture newLecture = new Lecture(
            now.plusDays(2),
            now.plusDays(2).plusHours(2),
            "Learning how to spell deprecated",
            10,
            course, null, new ArrayList<>(List.of()));

    private final Lecture lecture = new Lecture(
            now.plusDays(2),
            now.plusDays(2).plusHours(2),
            "Learning how to spell deprecated",
            10,
            course, lecturer, new ArrayList<>(List.of()));

    @Autowired
    private org.fuseri.modulelanguageschool.lecture.LectureMapper LectureMapper;

    @MockBean
    private CourseService courseService;

    @MockBean
    private UserService userService;

    @Test
    void mapNullToDto() {
        var createdDto = LectureMapper.mapToDto(null);

        Assertions.assertNull(createdDto);
    }

    @Test
    void mapToDto() {
        var createdDto = LectureMapper.mapToDto(lecture);

        Assertions.assertEquals(lectureDto, createdDto);
    }

    @Test
    void mapNullToLectureDto() {
        var createdLecture = LectureMapper.mapToLecture((LectureDto) null, courseService, userService);

        Assertions.assertNull(createdLecture);
    }

    @Test
    void mapToLectureDto() {
        when(courseService.findById(any())).thenReturn(course);
        when(userService.find(any())).thenReturn(lecturer);

        var createdLecture = LectureMapper.mapToLecture(lectureDto, courseService, userService);
        Assertions.assertEquals(lecture, createdLecture);
    }

    @Test
    void mapNullToList() {
        var lectureDtos = LectureMapper.mapToList(null);

        Assertions.assertNull(lectureDtos);
    }

    @Test
    void mapToEmptyList() {
        var lectureDtos = LectureMapper.mapToList(Collections.emptyList());

        Assertions.assertEquals(lectureDtos.size(), 0);
    }

    @Test
    void mapToList() {
        when(courseService.findById(anyLong())).thenReturn(course);
        when(userService.find(anyLong())).thenReturn(lecturer);

        var lectureDtos = LectureMapper.mapToList(Collections.singletonList(lecture));

        Assertions.assertEquals(1, lectureDtos.size());
        Assertions.assertEquals(lectureDto, lectureDtos.get(0));
    }

    @Test
    void mapNullToLectureLectureCreateDto() {
        var createdLecture = LectureMapper.mapToLecture((LectureCreateDto) null, courseService);

        Assertions.assertNull(createdLecture);
    }

    @Test
    void mapToLectureLectureCreateDto() {
        when(courseService.findById(any())).thenReturn(course);

        var createdLecture = LectureMapper.mapToLecture(lectureCreateDto, courseService);

        Assertions.assertEquals(newLecture, createdLecture);
    }

}

