package org.fuseri.modulecertificate;

import org.fuseri.model.dto.course.CourseDto;
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.CertificateRepository;
import org.fuseri.modulecertificate.certificate.CertificateService;
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 org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.server.ResponseStatusException;

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

import static org.mockito.Mockito.*;

@SpringBootTest
final class CertificateServiceTests {

    @MockBean
    private CertificateRepository certificateRepository;

    @Autowired
    private CertificateService certificateService;

    private final UserDto USER = new UserDto("novakovat",
            "novakova@gamil.com", "Tereza", "Nováková",new HashMap<>());
    private final CourseDto COURSE = new CourseDto("AJ1", 10,
            LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1);
    private final Certificate certificate = new Certificate(USER.getId(),
            Instant.now(), COURSE.getId(), "fileName");
    private final List<Certificate> certificates = List.of(certificate, certificate);

    @Test
    void save() {
        when(certificateRepository.save(certificate)).thenReturn(certificate);

        Certificate result = certificateService.save(certificate);

        Assertions.assertEquals(certificate, result);
        verify(certificateRepository).save(certificate);
    }

    @Test
    void notFoundById() {
        when(certificateRepository.findById(certificate.getId())).thenReturn(Optional.empty());

        Assertions.assertThrows(ResponseStatusException.class, () -> certificateService.findById(certificate.getId()));

    }

    @Test
    void findById() {
        when(certificateRepository.findById(certificate.getId())).thenReturn(Optional.of(certificate));

        Certificate result = certificateService.findById(certificate.getId());

        Assertions.assertEquals(certificate, result);
        verify(certificateRepository).findById(certificate.getId());
    }



    @Test
    void findByUserId() {
        when(certificateRepository.findCertificateByUserId(USER.getId())).thenReturn(certificates);

        List<Certificate> result = certificateService.findByUserId(USER.getId());

        Assertions.assertEquals(certificates, result);
        verify(certificateRepository).findCertificateByUserId(USER.getId());
    }

    @Test
    void findByUserIdAndCourseId() {
        when(certificateRepository.findCertificateByUserIdAndCourseId(USER.getId(), COURSE.getId())).thenReturn(certificates);

        List<Certificate> result = certificateService.findByUserIdAndCourseId(USER.getId(), COURSE.getId());

        Assertions.assertEquals(certificates, result);
        verify(certificateRepository).findCertificateByUserIdAndCourseId(USER.getId(), COURSE.getId());

    }

    @Test
    void delete() {
        certificateService.delete(certificate.getId());

        verify(certificateRepository).deleteById(certificate.getId());
    }

    @Test
    void findAll() {
        Pageable pageable = PageRequest.of(0, 10);
        Page<Certificate> page = new PageImpl<>(Collections.emptyList(), pageable, 0);

        when(certificateRepository.findAll(pageable)).thenReturn(page);

        Page<Certificate> result = certificateService.findAll(pageable);

        Assertions.assertEquals(page, result);
        verify(certificateRepository).findAll(pageable);

    }

}
