/*
 *******************************************************************************
 * Copyright (c) 2019 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************
 */
package org.eclipse.openk.contactbasedata.service;

import org.eclipse.openk.contactbasedata.config.TestConfiguration;
import org.eclipse.openk.contactbasedata.exceptions.NotFoundException;
import org.eclipse.openk.contactbasedata.exceptions.OperationDeniedException;
import org.eclipse.openk.contactbasedata.model.TblAssignmentModulContact;
import org.eclipse.openk.contactbasedata.model.TblContact;
import org.eclipse.openk.contactbasedata.repository.AssignmentModulContactRepository;
import org.eclipse.openk.contactbasedata.repository.ContactRepository;
import org.eclipse.openk.contactbasedata.support.MockDataHelper;
import org.eclipse.openk.contactbasedata.viewmodel.AssignmentModulContactDto;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.hibernate.validator.internal.util.Contracts.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

@DataJpaTest
@ContextConfiguration(classes = {TestConfiguration.class})

public class AssignmentModulContactServiceTest {
    @Qualifier("myAssignmentModulContactService")
    @Autowired
    private AssignmentModulContactService assignmentService;

    @MockBean
    private AssignmentModulContactRepository assignmentRepository;

    @MockBean
    private ContactRepository contactRepository;


    @Test
    public void shouldReturnAssignmentsByContactUuid() {

        List<TblAssignmentModulContact> listTblAssignments = MockDataHelper.mockTblAssignmentsList();
        when(assignmentRepository.findByTblContactUuid( any(UUID.class)) ).thenReturn(listTblAssignments);

        List<AssignmentModulContactDto> tblAssignmentsList = assignmentService.getAssignments(UUID.randomUUID());
        assertEquals(tblAssignmentsList.size(), 2 );
    }


    @Test
    public void shouldReturnSingleAssignmentsByContactUuidAndAssignUuid() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        when(assignmentRepository.findByUuid(any(UUID.class)) ).thenReturn(Optional.of(tblAssignment));

        AssignmentModulContactDto assignmentDto = assignmentService.getAssignment(
                tblAssignment.getTblContact().getUuid(), UUID.randomUUID());
        assertEquals(assignmentDto.getContactUuid(), tblAssignment.getTblContact().getUuid() );

        // try it with a not matching contactUUID
        assertThrows(NotFoundException.class, () -> assignmentService.getAssignment(UUID.randomUUID(), UUID.randomUUID()));

        // try it with an empty repository result
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.empty());
        assertThrows(NotFoundException.class, () ->
                assignmentService.getAssignment(assignmentDto.getContactUuid(), UUID.randomUUID()));
    }
    @Test
    public void shouldUpdateAssignment() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndUuidAndModulNameIsNotSame(anyLong(),any(UUID.class),anyString())).thenReturn(0L);

        AssignmentModulContactDto savedAssignment = assignmentService.updateAssignment(assignmentDto.getUuid(), assignmentDto);

        assertEquals(tblAssignment.getTblContact().getUuid(), savedAssignment.getContactUuid());
        assertEquals(tblAssignment.getUuid(), savedAssignment.getUuid());
        assertEquals(tblAssignment.getAssignmentDate(), savedAssignment.getAssignmentDate());
        assertEquals(tblAssignment.getAssignmentNote(), savedAssignment.getAssignmentNote());
        assertEquals(tblAssignment.getDeletionLockUntil(), savedAssignment.getDeletionLockUntil());
        assertEquals(tblAssignment.getExpiringDate(), savedAssignment.getExpiringDate());
        assertEquals(tblAssignment.getModulName(), savedAssignment.getModulName());
    }

    @Test
    public void shouldNotUpdateAssignment_Exception1() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.empty());
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndUuidAndModulNameIsNotSame(anyLong(),any(UUID.class),anyString())).thenReturn(0L);

        assertThrows( NotFoundException.class, () -> assignmentService.updateAssignment(assignmentDto.getUuid(), assignmentDto));
    }

    @Test
    public void shouldNotUpdateAssignment_Exception2() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.empty());
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndUuidAndModulNameIsNotSame(anyLong(),any(UUID.class),anyString())).thenReturn(0L);

        assertThrows( NotFoundException.class, () -> assignmentService.updateAssignment(assignmentDto.getUuid(), assignmentDto));
    }

    @Test
    public void shouldNotUpdateAssignment_Exception3() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndUuidAndModulNameIsNotSame(anyLong(),any(UUID.class),anyString())).thenReturn(4L);

        assertThrows( OperationDeniedException.class, () -> assignmentService.updateAssignment(assignmentDto.getUuid(), assignmentDto));

    }

    @Test
    public void shouldInsertAssignment() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndModuleName(anyLong(), anyString())).thenReturn(0L);

        AssignmentModulContactDto savedAssignment = assignmentService.insertAssignment(assignmentDto.getUuid(), assignmentDto);

        assertNotNull(savedAssignment.getContactUuid());
        assertEquals(tblAssignment.getTblContact().getUuid(), savedAssignment.getContactUuid());
        assertEquals(tblAssignment.getAssignmentDate(), savedAssignment.getAssignmentDate());
        assertEquals(tblAssignment.getAssignmentNote(), savedAssignment.getAssignmentNote());
        assertEquals(tblAssignment.getDeletionLockUntil(), savedAssignment.getDeletionLockUntil());
        assertEquals(tblAssignment.getExpiringDate(), savedAssignment.getExpiringDate());
        assertEquals(tblAssignment.getModulName(), savedAssignment.getModulName());

    }

    @Test
    public void shouldNotInsertAssignment_Exception_1() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.empty());
        when(assignmentRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);
        when(assignmentRepository.countByContactIdAndModuleName(anyLong(), anyString())).thenReturn(0L);

        assertThrows( NotFoundException.class, () -> assignmentService.insertAssignment(assignmentDto.getUuid(), assignmentDto));

    }


    @Test
    public void shouldNotInsertAssignment_Exception_2() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        AssignmentModulContactDto assignmentDto = MockDataHelper.mockAssignmentModulContactDto();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.countByContactIdAndModuleName(anyLong(), anyString())).thenReturn(2L);
        when(assignmentRepository.save(any(TblAssignmentModulContact.class))).thenReturn(tblAssignment);

        assertThrows( OperationDeniedException.class, () -> assignmentService.insertAssignment(assignmentDto.getUuid(), assignmentDto));

    }


    @Test
    public void shouldDeleteAssignment() {
        TblAssignmentModulContact tblAssignment = MockDataHelper.mockTblAssignmentModulContact();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAssignment.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(assignmentRepository.findByTblContactAndUuid(any(TblContact.class), any(UUID.class))).thenReturn(Optional.of(tblAssignment));
        Mockito.doNothing().when(assignmentRepository).delete( isA( TblAssignmentModulContact.class ));

        assignmentService.deleteAssignment(tblContact.getUuid(), tblAssignment.getUuid());

        Mockito.verify(assignmentRepository, times(1)).delete( tblAssignment );
    }

}
