package com.braintree.converters.populators;

import com.braintree.model.BrainTreePaymentInfoModel;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.commercefacades.order.data.CCPaymentInfoData;
import de.hybris.platform.commercefacades.user.converters.populator.AddressReversePopulator;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.core.model.user.AddressModel;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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

    private static final String CARD_NUMBER = "cardNumber";
    private static final String ACCOUNT_HOLDER_NAME = "testName";
    private static final String CARD_HOLDER_NAME = "cardHolderName";
    private static final String SUBSCRIPTION_ID = "subscriptionID";
    private static final boolean IS_SAVED = true;
    private static final String PAYMENT_METHOD_TOKEN = "paymentMethodToken";
    private static final String PAYER = "payer";
    private static final String NONCE = "nonce";
    private static final String EXPIRATION_YEAR = "2023";
    private static final String EXPIRATION_MONTH = "01";
    private static final String COMA_SEPARATOR = ", ";

    @Mock
    private AddressReversePopulator addressReversePopulator;
    @Mock
    private BrainTreePaymentInfoModel model;
    @Mock
    private AddressModel addressModel;

    @InjectMocks
    private BraintreePaymentInfoReversePopulator unit;

    @Test
    public void populateShouldSetNeededFields() {
        CCPaymentInfoData data = new CCPaymentInfoData();

        data.setCardNumber(CARD_NUMBER);
        data.setExpiryYear(EXPIRATION_YEAR);
        data.setExpiryMonth(EXPIRATION_MONTH);
        data.setAccountHolderName(ACCOUNT_HOLDER_NAME);
        data.setCardholderName(CARD_HOLDER_NAME);
        data.setSubscriptionId(SUBSCRIPTION_ID);
        data.setSaved(IS_SAVED);
        data.setPaymentMethodToken(PAYMENT_METHOD_TOKEN);
        data.setPayer(PAYER);
        data.setPaymentMethodNonce(NONCE);

        unit.populate(data, model);

        verify(model).setCardNumber(CARD_NUMBER);
        verify(model).setExpirationYear(EXPIRATION_YEAR);
        verify(model).setExpirationMonth(EXPIRATION_MONTH);
        verify(model).setImageSource(ACCOUNT_HOLDER_NAME);
        verify(model).setCardholderName(CARD_HOLDER_NAME);
        verify(model).setPaymentProvider(SUBSCRIPTION_ID);
        verify(model).setSaved(IS_SAVED);
        verify(model).setPaymentMethodToken(PAYMENT_METHOD_TOKEN);
        verify(model).setPayer(PAYER);
        verify(model).setNonce(NONCE);
    }

    @Test
    public void shouldPopulateBillingAddress() {
        CCPaymentInfoData data = new CCPaymentInfoData();
        AddressData addressData = new AddressData();

        data.setBillingAddress(addressData);

        when(model.getBillingAddress()).thenReturn(addressModel);
        when(addressModel.getLastname()).thenReturn(COMA_SEPARATOR);

        unit.populate(data, model);

        verify(addressReversePopulator).populate(addressData, addressModel);
        verify(addressModel).setLastname(null);
    }

    @Test
    public void shouldPopulateBillingAddressAndSkipLastName() {
        CCPaymentInfoData data = new CCPaymentInfoData();
        AddressData addressData = new AddressData();

        data.setBillingAddress(addressData);

        when(model.getBillingAddress()).thenReturn(addressModel);
        when(addressModel.getLastname()).thenReturn("lastName");

        unit.populate(data, model);

        verify(addressReversePopulator).populate(addressData, addressModel);
        verify(addressModel, never()).setLastname(null);
    }

    @Test
    public void shouldNotPopulateBillingAddressIfAddressDataNull() {
        CCPaymentInfoData data = new CCPaymentInfoData();

        when(model.getBillingAddress()).thenReturn(addressModel);

        unit.populate(data, model);

        verify(addressReversePopulator, never()).populate(any(), any());
    }

    @Test
    public void shouldNotPopulateBillingAddressIfAddressModelNull() {
        CCPaymentInfoData data = new CCPaymentInfoData();
        AddressData addressData = new AddressData();

        data.setBillingAddress(addressData);

        unit.populate(data, model);

        verify(addressReversePopulator, never()).populate(any(), any());
    }

}
