/*
 *******************************************************************************
 * 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.RefAddressType;
import org.eclipse.openk.contactbasedata.model.RefSalutation;
import org.eclipse.openk.contactbasedata.model.TblAddress;
import org.eclipse.openk.contactbasedata.model.TblContact;
import org.eclipse.openk.contactbasedata.repository.AddressRepository;
import org.eclipse.openk.contactbasedata.repository.AddressTypeRepository;
import org.eclipse.openk.contactbasedata.repository.ContactRepository;
import org.eclipse.openk.contactbasedata.repository.SalutationRepository;
import org.eclipse.openk.contactbasedata.support.MockDataHelper;
import org.eclipse.openk.contactbasedata.viewmodel.AddressDto;
import org.eclipse.openk.contactbasedata.viewmodel.SalutationDto;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
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 AddressServiceTest {
    @Qualifier("myAddressService")
    @Autowired
    private AddressService addressService;

    @MockBean
    private AddressRepository addressRepository;

    @MockBean
    private ContactRepository contactRepository;

    @MockBean
    private AddressTypeRepository addressTypeRepository;

    @Test
    public void shouldReturnAddressesByContactUuid() {

        List<TblAddress> listTblAddresses = MockDataHelper.mockTblAddressList();
        when(addressRepository.findByTblContactUuid( any(UUID.class)) ).thenReturn(listTblAddresses);

        List<AddressDto> dtoList = addressService.getAddressesByContactUuid(UUID.randomUUID());
        assertEquals(dtoList.size(), 2 );
    }

    @Test
    public void shouldReturnAddressesByContactUuidAndAddressUuid() {

        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        when(addressRepository.findByUuid( any(UUID.class)) ).thenReturn(Optional.of(tblAddress));

        AddressDto dto = addressService.getAddress(tblAddress.getTblContact().getUuid(), UUID.randomUUID());
        assertEquals(tblAddress.getUuid(), dto.getUuid() );
    }

    @Test
    public void shouldUpdateAddress() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAddress));
        when(addressRepository.save(any(TblAddress.class))).thenReturn(tblAddress);
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(refAddressType));

        AddressDto savedAddress = addressService.updateAddress(addressDto.getUuid(), addressDto);

        assertEquals(tblAddress.getTblContact().getUuid(), savedAddress.getContactUuid());
        assertEquals(tblAddress.getUuid(), savedAddress.getUuid());
        assertEquals(tblAddress.getCommunity(), savedAddress.getCommunity());
        assertEquals(tblAddress.getCommunitySuffix(), savedAddress.getCommunitySuffix());
        assertEquals(tblAddress.getHousenumber(), savedAddress.getHousenumber());
        assertEquals(tblAddress.getIsMainAddress(), savedAddress.getIsMainAddress());
        assertEquals(tblAddress.getLatitude(), savedAddress.getLatitude());
        assertEquals(tblAddress.getLongitude(), savedAddress.getLongitude());
        assertEquals(tblAddress.getPostcode(), savedAddress.getPostcode());
        assertEquals(tblAddress.getStreet(), savedAddress.getStreet());
        assertEquals(tblAddress.getRefAddressType().getUuid(), savedAddress.getAddressTypeUuid()); //klappt nicht, da UUIDs von RefAddressType unterschiedlich
        assertEquals(tblAddress.getUrlMap(), savedAddress.getUrlMap());
        assertEquals(tblAddress.getWgs_84_zone(), savedAddress.getWgs84Zone());
    }

    @Test
    public void shouldNotUpdateAddress_Exception1() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.empty());
        when(addressRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAddress));
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(refAddressType));
        when(addressRepository.save(any(TblAddress.class)))
                .then((Answer<TblAddress>) invocation -> {
                    Object[] args = invocation.getArguments();
                    return (TblAddress) args[0];
                });

        assertThrows( NotFoundException.class, () -> addressService.updateAddress(addressDto.getUuid(), addressDto));
    }

    @Test
    public void shouldNotUpdateAddress_Exception2() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAddress));
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.empty());
        when(addressRepository.save(any(TblAddress.class)))
                .then((Answer<TblAddress>) invocation -> {
                    Object[] args = invocation.getArguments();
                    return (TblAddress) args[0];
                });

        assertThrows( NotFoundException.class, () -> addressService.updateAddress(addressDto.getUuid(), addressDto));
    }

    @Test
    public void shouldNotUpdateAddress_Exception3() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        addressDto.setIsMainAddress(true);
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        tblAddress.setIsMainAddress(true);
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(tblAddress));
        when(addressRepository.countByContactIdAndMainAddressIsNotSame(any(Long.class), anyBoolean(), any(UUID.class)) ).thenReturn(3L);
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(refAddressType));

        when(addressRepository.save(any(TblAddress.class)))
                .then((Answer<TblAddress>) invocation -> {
                    Object[] args = invocation.getArguments();
                    return (TblAddress) args[0];
                });

        assertThrows( OperationDeniedException.class, () -> addressService.updateAddress(addressDto.getUuid(), addressDto));

    }

    @Test
    public void shouldInsertAddress() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.save(any(TblAddress.class))).thenReturn(tblAddress);
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(refAddressType));

        AddressDto savedAddress = addressService.insertAddress(addressDto.getUuid(), addressDto);

        assertNotNull(savedAddress.getContactUuid());
        assertEquals(tblAddress.getTblContact().getUuid(), savedAddress.getContactUuid());
        assertEquals(tblAddress.getUuid(), savedAddress.getUuid());
        assertEquals(tblAddress.getCommunity(), savedAddress.getCommunity());
        assertEquals(tblAddress.getCommunitySuffix(), savedAddress.getCommunitySuffix());
        assertEquals(tblAddress.getHousenumber(), savedAddress.getHousenumber());
        assertEquals(tblAddress.getIsMainAddress(), savedAddress.getIsMainAddress());
        assertEquals(tblAddress.getLatitude(), savedAddress.getLatitude());
        assertEquals(tblAddress.getLongitude(), savedAddress.getLongitude());
        assertEquals(tblAddress.getPostcode(), savedAddress.getPostcode());
        assertEquals(tblAddress.getStreet(), savedAddress.getStreet());
        assertEquals(tblAddress.getRefAddressType().getUuid(), savedAddress.getAddressTypeUuid());
        assertEquals(tblAddress.getUrlMap(), savedAddress.getUrlMap());
        assertEquals(tblAddress.getWgs_84_zone(), savedAddress.getWgs84Zone());

    }

    @Test
    public void shouldNotInsertAddress_Exception_1() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.empty());
        when(addressRepository.save(any(TblAddress.class))).thenReturn(tblAddress);
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.of(refAddressType));

        assertThrows( NotFoundException.class, () -> addressService.insertAddress(addressDto.getUuid(), addressDto));

    }

    @Test
    public void shouldNotInsertAddress_Exception_2() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        RefAddressType refAddressType = MockDataHelper.mockRefAddressType();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.save(any(TblAddress.class))).thenReturn(tblAddress);
        when (addressTypeRepository.findByUuid(any(UUID.class))).thenReturn(Optional.empty());

        assertThrows( NotFoundException.class, () -> addressService.insertAddress(addressDto.getUuid(), addressDto));
    }


    @Test
    public void shouldNotInsertAddress_Exception3() {
        AddressDto addressDto = MockDataHelper.mockAddressDto();
        addressDto.setIsMainAddress(true);
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        tblAddress.setIsMainAddress(true);
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.countByContactIdAndIsMainAddress(anyLong(), anyBoolean())).thenReturn(2L);
        when(addressRepository.save(any(TblAddress.class))).thenReturn(tblAddress);

        assertThrows( OperationDeniedException.class, () -> addressService.insertAddress(addressDto.getUuid(), addressDto));

    }


    @Test
    public void shouldDeleteAddress() {
        TblAddress tblAddress = MockDataHelper.mockTblAddress();
        TblContact tblContact = MockDataHelper.mockTblContact();
        tblAddress.setTblContact(tblContact);

        when (contactRepository.findByUuid( any(UUID.class))).thenReturn(Optional.of(tblContact));
        when(addressRepository.findByTblContactAndUuid(any(TblContact.class), any(UUID.class))).thenReturn(Optional.of(tblAddress));
        Mockito.doNothing().when(addressRepository).delete( isA( TblAddress.class ));

        addressService.deleteAddress(tblContact.getUuid(), tblAddress.getUuid());

        Mockito.verify(addressRepository, times(1)).delete( tblAddress );
    }

}
