package org.fuseri.modulecertificate;

import org.fuseri.model.dto.certificate.CertificateCreateDto;
import org.fuseri.model.dto.certificate.CertificateSimpleDto;
import org.fuseri.model.dto.course.CourseCertificateDto;
import org.fuseri.model.dto.course.LanguageTypeDto;
import org.fuseri.model.dto.course.ProficiencyLevelDto;
import org.fuseri.model.dto.user.UserDto;
import org.fuseri.modulecertificate.certificate.Certificate;
import org.fuseri.modulecertificate.certificate.CertificateMapper;
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.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

@SpringBootTest
final class CertificateMapperTests {

    private final UserDto USER = new UserDto("novakovat",
            "novakova@gamil.com", "Tereza", "Nováková",new HashMap<>());
    private final CourseCertificateDto COURSE = new CourseCertificateDto("AJ1", 10,
            LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1);
    private final Instant instant = Instant.now();
    private final String fileName = "fileName";
    private final String file = "file";
    private final CertificateSimpleDto certificateDto = new CertificateSimpleDto(0L, USER.getId(),
            instant, COURSE.getId(), fileName);
    private final Certificate certificate = new Certificate(USER.getId(),
            instant, COURSE.getId(), fileName);
    private final CertificateCreateDto certificateCreateDto = new CertificateCreateDto(USER, COURSE);
    @Autowired
    private CertificateMapper certificateMapper;

    @Test
    void mapNullToSimpleDto() {
        var createdSimpleDto = certificateMapper.mapToSimpleDto(null);

        Assertions.assertNull(createdSimpleDto);
    }

    @Test
    void mapToSimpleDto() {
        var createdSimpleDto = certificateMapper.mapToSimpleDto(certificate);

        Assertions.assertEquals(createdSimpleDto.getUserId(), certificateDto.getUserId());
        Assertions.assertEquals(createdSimpleDto.getGeneratedAt(), certificateDto.getGeneratedAt());
        Assertions.assertEquals(createdSimpleDto.getCourseId(), certificateDto.getCourseId());
        Assertions.assertEquals(createdSimpleDto.getCertificateFileName(), certificateDto.getCertificateFileName());
    }

    @Test
    void mapNullToCertificate() {
        var createdCertificate = certificateMapper.mapToCertificate(null, Instant.now(), "");

        Assertions.assertNull(createdCertificate);
    }

    @Test
    void mapToCertificate() {
        var createdCertificate = certificateMapper.mapToCertificate(certificateCreateDto, Instant.now(), "");

        Assertions.assertEquals(createdCertificate.getUserId(), certificateDto.getUserId());
        Assertions.assertNotNull(createdCertificate.getGeneratedAt());
        Assertions.assertEquals(createdCertificate.getCourseId(), certificateDto.getCourseId());
    }

    @Test
    void mapNullToList() {
        var certificateSimpleDtos = certificateMapper.mapToList(null);

        Assertions.assertNull(certificateSimpleDtos);
    }

    @Test
    void mapToEmptyList() {
        var certificateSimpleDtos = certificateMapper.mapToList(Collections.emptyList());

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

    @Test
    void mapToList() {
        var certificateSimpleDtos = certificateMapper.mapToList(Collections.singletonList(certificate));

        Assertions.assertEquals(certificateSimpleDtos.size(), 1);
        Assertions.assertEquals(certificateSimpleDtos.get(0).getUserId(), certificateDto.getUserId());
        Assertions.assertEquals(certificateSimpleDtos.get(0).getGeneratedAt(), certificateDto.getGeneratedAt());
        Assertions.assertEquals(certificateSimpleDtos.get(0).getCourseId(), certificateDto.getCourseId());
        Assertions.assertEquals(certificateSimpleDtos.get(0).getCertificateFileName(), certificateDto.getCertificateFileName());


    }

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

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

    @Test
    void mapToPageDto() {
        List<Certificate> certificates = List.of(certificate);
        Page<Certificate> page = new PageImpl<>(certificates, PageRequest.of(0, 1), certificates.size());
        Page<CertificateSimpleDto> pageDto = certificateMapper.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(certificate.getId(), pageDto.getContent().get(0).getId());
        Assertions.assertEquals(certificate.getGeneratedAt(), pageDto.getContent().get(0).getGeneratedAt());
        Assertions.assertEquals(certificate.getUserId(), pageDto.getContent().get(0).getUserId());
        Assertions.assertEquals(certificate.getCourseId(), pageDto.getContent().get(0).getCourseId());
        Assertions.assertEquals(certificate.getCertificateFileName(), pageDto.getContent().get(0).getCertificateFileName());
    }

}
