package com.braintree.populators;

import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.model.BraintreeCustomerDetailsModel;
import com.braintreegateway.Address;
import com.braintreegateway.CreditCard;
import com.braintreegateway.Customer;
import com.braintreegateway.PaymentMethod;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.user.AddressModel;
import de.hybris.platform.servicelayer.dto.converter.Converter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.junit.Assert.assertNull;

@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class BraintreeCustomerDetailsPopulatorTest {

    private static final String ID = "Id";
    private static final String GRAPH_QL_ID = "GraphQLId";
    private static final String COMPANY = "Company";
    private static final String EMAIL = "Email";
    private static final String FAX = "Fax";
    private static final String FIRST_NAME = "User";
    private static final String LAST_NAME = "Tester";
    private static final String PHONE_NUMBER = "+8888888888";
    private static final String WEBSITE = "Website";

    @InjectMocks
    private BraintreeCustomerDetailsPopulator unit;

    @Mock
    private Customer customer;
    @Mock
    private Calendar calendar;
    @Mock
    private List<Address> addressList;
    @Mock
    private Iterator<Address> addressIterator;
    @Mock
    private Address address;
    @Mock
    private Converter<Address, AddressModel> braintreeAddressConverter;
    @Mock
    private Converter<PaymentMethod, BrainTreePaymentInfoModel> paymentMethodConverter;
    @Mock
    private AddressModel addressModel;
    @Mock
    private List<CreditCard> creditCardList;
    @Mock
    private CreditCard creditCard;
    @Mock
    private Iterator<CreditCard> creditCardIterator;
    @Mock
    private BrainTreePaymentInfoModel paymentInfoModel;

    @Test
    public void shouldPopulateCustomerToBraintreeCustomerDetailsModelTest(){
        BraintreeCustomerDetailsModel target = new BraintreeCustomerDetailsModel();

        when(customer.getId()).thenReturn(ID);
        when(customer.getGraphQLId()).thenReturn(GRAPH_QL_ID);
        when(customer.getCompany()).thenReturn(COMPANY);
        when(customer.getCreatedAt()).thenReturn(calendar);
        when(customer.getEmail()).thenReturn(EMAIL);
        when(customer.getFax()).thenReturn(FAX);
        when(customer.getFirstName()).thenReturn(FIRST_NAME);
        when(customer.getLastName()).thenReturn(LAST_NAME);
        when(customer.getUpdatedAt()).thenReturn(calendar);
        when(customer.getPhone()).thenReturn(PHONE_NUMBER);
        when(customer.getWebsite()).thenReturn(WEBSITE);
        when(customer.getAddresses()).thenReturn(addressList);
        when(addressList.iterator()).thenReturn(addressIterator);
        when(addressIterator.hasNext()).thenReturn(true, false);
        when(addressIterator.next()).thenReturn(address);
        when(braintreeAddressConverter.convert(address)).thenReturn(addressModel);
        when(customer.getCreditCards()).thenReturn(creditCardList);
        when(creditCardList.iterator()).thenReturn(creditCardIterator);
        when(creditCardIterator.hasNext()).thenReturn(true, false);
        when(creditCardIterator.next()).thenReturn(creditCard);
        when(paymentMethodConverter.convert(creditCard)).thenReturn(paymentInfoModel);

        unit.populate(customer, target);

        assertEquals(ID, target.getId());
        assertEquals(GRAPH_QL_ID, target.getGraphQLId());
        assertEquals(COMPANY, target.getCompany());
        assertEquals(calendar.getTime(), target.getCreatedAt());
        assertEquals(EMAIL, target.getEmail());
        assertEquals(FAX, target.getFax());
        assertEquals(FIRST_NAME, target.getFirstName());
        assertEquals(LAST_NAME, target.getLastName());
        assertEquals(addressModel, target.getAddresses().get(0));
        assertEquals(paymentInfoModel, target.getPaymentMethods().get(0));
    }

    @Test
    public void shouldPopulateWithCreatedAtNullAndAddressNull(){
        BraintreeCustomerDetailsModel target = new BraintreeCustomerDetailsModel();

        when(customer.getId()).thenReturn(ID);
        when(customer.getGraphQLId()).thenReturn(GRAPH_QL_ID);
        when(customer.getCompany()).thenReturn(COMPANY);
        when(customer.getCreatedAt()).thenReturn(calendar);
        when(customer.getEmail()).thenReturn(EMAIL);
        when(customer.getFax()).thenReturn(FAX);
        when(customer.getFirstName()).thenReturn(FIRST_NAME);
        when(customer.getLastName()).thenReturn(LAST_NAME);
        when(customer.getUpdatedAt()).thenReturn(null);
        when(customer.getPhone()).thenReturn(PHONE_NUMBER);
        when(customer.getWebsite()).thenReturn(WEBSITE);
        when(customer.getAddresses()).thenReturn(null);
        when(customer.getCreditCards()).thenReturn(null);

        unit.populate(customer, target);

        assertEquals(ID, target.getId());
        assertEquals(GRAPH_QL_ID, target.getGraphQLId());
        assertEquals(COMPANY, target.getCompany());
        assertNull(target.getCreatedAt());
        assertEquals(EMAIL, target.getEmail());
        assertEquals(FAX, target.getFax());
        assertEquals(FIRST_NAME, target.getFirstName());
        assertEquals(LAST_NAME, target.getLastName());
        assertNull(target.getAddresses());
        assertEquals(0, target.getPaymentMethods().size());
    }
}