package org.fuseri.modulelanguageschool.course;

import org.fuseri.model.dto.course.CourseCreateDto;
import org.fuseri.model.dto.course.CourseDto;
import org.fuseri.model.dto.course.LanguageTypeDto;
import org.fuseri.model.dto.course.ProficiencyLevelDto;
import org.fuseri.modulelanguageschool.user.UserService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@SpringBootTest
final class CourseMapperTest {

    private final CourseDto courseDto = new CourseDto("AJ1", 10,
            LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1, new ArrayList<>(), false);
    private final CourseCreateDto courseCreateDto = new CourseCreateDto("AJ1", 10,
            LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1);
    private final Course course = new Course("AJ1", 10,
            Language.ENGLISH, ProficiencyLevel.A1);

    @Autowired
    private CourseMapper CourseMapper;

    @Autowired
    private UserService userService;

    @BeforeEach
    void setUp() {
        course.setId(1L);
        courseDto.setId(1L);
    }

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

        Assertions.assertNull(createdDto);
    }

    @Test
    void mapToDto() {
        var createdDto = CourseMapper.mapToDto(course);

        Assertions.assertNotNull(createdDto);
    }

    @Test
    void mapNullToCourseCourseDto() {
        var createdCourse = CourseMapper.mapToCourse((CourseDto) null, null);

        Assertions.assertNull(createdCourse);
    }

    @Test
    void mapToCourseCourseDto() {
        var createdCourse = CourseMapper.mapToCourse(courseDto, userService);

        Assertions.assertNotNull(createdCourse);
    }

    @Test
    void mapNullToList() {
        var courseDtos = CourseMapper.mapToList(null);

        Assertions.assertNull(courseDtos);
    }

    @Test
    void mapToEmptyList() {
        var courseDtos = CourseMapper.mapToList(Collections.emptyList());

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

    @Test
    void mapToList() {
        var courseDtos = CourseMapper.mapToList(Collections.singletonList(course));

        Assertions.assertEquals(1, courseDtos.size());
    }

    @Test
    void mapToEmptyPageDto() {
        Page<CourseDto> pageDto = CourseMapper.mapToPageDto(Page.empty());

        Assertions.assertEquals(1, pageDto.getTotalPages());
    }

    @Test
    void mapToPageDto() {
        List<Course> courses = List.of(course);
        Page<Course> page = new PageImpl<>(courses, PageRequest.of(0, 1), courses.size());
        Page<CourseDto> pageDto = CourseMapper.mapToPageDto(page);

        Assertions.assertEquals(page.getTotalPages(), pageDto.getTotalPages());
        Assertions.assertEquals(page.getNumber(), pageDto.getNumber());
        Assertions.assertEquals(page.getNumberOfElements(), pageDto.getNumberOfElements());
        Assertions.assertEquals(page.getSize(), pageDto.getSize());
        Assertions.assertEquals(page.getTotalElements(), pageDto.getTotalElements());

//            Assertions.assertEquals(courseDto, pageDto.getContent().get(0));
    }

    @Test
    void mapNullToCourseCourseCreateDto() {
        var createdCourse = CourseMapper.mapToCourse((CourseCreateDto) null);

        Assertions.assertNull(createdCourse);
    }

    @Test
    void mapToCourseCourseCreateDto() {
        var createdCourse = CourseMapper.mapToCourse(courseCreateDto);

        Assertions.assertEquals(course, createdCourse);
    }

}
