package com.braintree.populators;

import com.braintree.enums.BrainTreeCardType;
import com.braintree.enums.BrainTreePaymentMethod;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintreegateway.Address;
import com.braintreegateway.AmexExpressCheckoutCard;
import com.braintreegateway.AndroidPayCard;
import com.braintreegateway.ApplePayCard;
import com.braintreegateway.CreditCard;
import com.braintreegateway.PayPalAccount;
import com.braintreegateway.VisaCheckoutCard;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.user.AddressModel;
import de.hybris.platform.servicelayer.dto.converter.Converter;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Calendar;

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

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

    private static final String TOKEN = "Token";
    private static final String IMAGE_URL = "ImageURL";
    private static final String PAY_PAL_EMAIL = "PayPalEmail";
    private static final String APPLE_PAY_TOKEN = "ApplePayToken";
    private static final String APPLE_PAY_IMAGE_URL = "ApplePayImageURL";
    private static final String EXPIRATION_MONTH = "ExpirationMonth";
    private static final String EXPIRATION_YEAR = "ExpirationYear";
    private static final String CARD_HOLDER_NAME = "CardHolderName";
    private static final String LAST_FOUR = "1234";
    private static final String MASKED_CARD_NUMBER = "******1234";
    private static final boolean IS_DEFAULT = true;
    private static final String CUSTOMER_ID = "CustomerId";
    private static final String CUSTOMER_LOCATION = "CustomerLocation";
    private static final String BIN = "BIN";

    @InjectMocks
    @Spy
    private BraintreePaymentMethodPopulator unit;
    @Mock
    private PayPalAccount payPalAccount;
    @Mock
    private CreditCard creditCard;
    @Mock
    private AndroidPayCard androidPayCard;
    @Mock
    private VisaCheckoutCard visaCheckoutCard;
    @Mock
    private Calendar calendar;
    @Mock
    private Converter<Address, AddressModel> braintreeAddressConverter;
    @Mock
    private Address billingAddress;
    @Mock
    private AddressModel billingAddressModel;
    @Mock
    private ApplePayCard applePayCard;
    @Mock
    private AmexExpressCheckoutCard amexExpressCheckoutCard;

    @Test
    public void shouldPopulateCreditCardToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(creditCard.getToken()).thenReturn(TOKEN);
        when(creditCard.getImageUrl()).thenReturn(IMAGE_URL);
        when(creditCard.isDefault()).thenReturn(IS_DEFAULT);
        when(creditCard.getBin()).thenReturn(StringUtils.EMPTY);
        when(creditCard.getLast4()).thenReturn(LAST_FOUR);
        when(creditCard.getUpdatedAt()).thenReturn(calendar);
        when(creditCard.getCustomerId()).thenReturn(CUSTOMER_ID);
        when(creditCard.getCardType()).thenReturn(BrainTreeCardType.MASTERCARD.getCode());
        when(creditCard.getCardholderName()).thenReturn(CARD_HOLDER_NAME);
        when(creditCard.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(creditCard.getExpirationYear()).thenReturn(EXPIRATION_YEAR);
        when(creditCard.getCustomerLocation()).thenReturn(CUSTOMER_LOCATION);
        when(creditCard.getCreatedAt()).thenReturn(calendar);
        when(creditCard.getBillingAddress()).thenReturn(billingAddress);
        when(braintreeAddressConverter.convert(billingAddress)).thenReturn(billingAddressModel);

        unit.populate(creditCard, target);

        assertEquals(TOKEN, target.getPaymentMethodToken());
        assertEquals(IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(MASKED_CARD_NUMBER, target.getPaymentInfo());
        assertEquals(CUSTOMER_ID, target.getCustomerId());
        assertEquals(BrainTreeCardType.MASTERCARD, target.getCardType());
        assertEquals(CARD_HOLDER_NAME, target.getCardholderName());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());
        assertEquals(CUSTOMER_LOCATION, target.getCustomerLocation());
        assertEquals(billingAddressModel, target.getBillingAddress());
        assertEquals(BrainTreePaymentMethod.CREDITCARD.getCode(), target.getPaymentProvider());
    }

    @Test
    public void shouldPopulatePayPalAccountToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(payPalAccount.getToken()).thenReturn(TOKEN);
        when(payPalAccount.getImageUrl()).thenReturn(IMAGE_URL);
        when(payPalAccount.isDefault()).thenReturn(IS_DEFAULT);
        when(payPalAccount.getEmail()).thenReturn(PAY_PAL_EMAIL);
        when(payPalAccount.getUpdatedAt()).thenReturn(calendar);
        when(payPalAccount.getCustomerId()).thenReturn(CUSTOMER_ID);
        when(payPalAccount.getCreatedAt()).thenReturn(calendar);

        unit.populate(payPalAccount, target);

        assertEquals(TOKEN, target.getPaymentMethodToken());
        assertEquals(IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(PAY_PAL_EMAIL, target.getPaymentInfo());
        assertEquals(CUSTOMER_ID, target.getCustomerId());
        assertEquals(BrainTreePaymentMethod.PAYPAL.getCode(), target.getPaymentProvider());
    }

    @Test
    public void shouldPopulateApplePayToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(applePayCard.getToken()).thenReturn(APPLE_PAY_TOKEN);
        when(applePayCard.getImageUrl()).thenReturn(APPLE_PAY_IMAGE_URL);
        when(applePayCard.isDefault()).thenReturn(IS_DEFAULT);
        when(applePayCard.getBin()).thenReturn(StringUtils.EMPTY);
        when(applePayCard.getLast4()).thenReturn(LAST_FOUR);
        when(applePayCard.getUpdatedAt()).thenReturn(calendar);
        when(applePayCard.getCreatedAt()).thenReturn(calendar);
        when(applePayCard.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(applePayCard.getExpirationYear()).thenReturn(EXPIRATION_YEAR);

        unit.populate(applePayCard, target);

        assertEquals(APPLE_PAY_TOKEN, target.getPaymentMethodToken());
        assertEquals(APPLE_PAY_IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(MASKED_CARD_NUMBER, target.getPaymentInfo());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());
        assertEquals(BrainTreePaymentMethod.APPLEPAYCARD.getCode(), target.getPaymentProvider());
    }

    @Test
    public void shouldPopulateAndroidCardToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(androidPayCard.getToken()).thenReturn(TOKEN);
        when(androidPayCard.getImageUrl()).thenReturn(IMAGE_URL);
        when(androidPayCard.isDefault()).thenReturn(IS_DEFAULT);
        when(androidPayCard.getBin()).thenReturn(StringUtils.EMPTY);
        when(androidPayCard.getLast4()).thenReturn(LAST_FOUR);
        when(androidPayCard.getUpdatedAt()).thenReturn(calendar);
        when(androidPayCard.getCreatedAt()).thenReturn(calendar);
        when(androidPayCard.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(androidPayCard.getExpirationYear()).thenReturn(EXPIRATION_YEAR);

        unit.populate(androidPayCard, target);

        assertEquals(TOKEN, target.getPaymentMethodToken());
        assertEquals(IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(MASKED_CARD_NUMBER, target.getPaymentInfo());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());
        assertEquals(BrainTreePaymentMethod.ANDROIDPAYCARD.getCode(), target.getPaymentProvider());
    }

    @Test
    public void shouldPopulateSrcToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(visaCheckoutCard.getToken()).thenReturn(TOKEN);
        when(visaCheckoutCard.getImageUrl()).thenReturn(IMAGE_URL);
        when(visaCheckoutCard.isDefault()).thenReturn(IS_DEFAULT);
        when(visaCheckoutCard.getUpdatedAt()).thenReturn(calendar);
        when(visaCheckoutCard.getCreatedAt()).thenReturn(calendar);
        when(visaCheckoutCard.getBin()).thenReturn(StringUtils.EMPTY);
        when(visaCheckoutCard.getLast4()).thenReturn(LAST_FOUR);
        when(visaCheckoutCard.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(visaCheckoutCard.getExpirationYear()).thenReturn(EXPIRATION_YEAR);

        unit.populate(visaCheckoutCard, target);

        assertEquals(TOKEN, target.getPaymentMethodToken());
        assertEquals(IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(MASKED_CARD_NUMBER, target.getPaymentInfo());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());
        assertEquals(BrainTreePaymentMethod.VISACHECKOUTCARD.getCode(), target.getPaymentProvider());
    }

    @Test
    public void shouldPopulateAmexToBrainTreePaymentInfoModelTest() {
        BrainTreePaymentInfoModel target = new BrainTreePaymentInfoModel();

        when(amexExpressCheckoutCard.getToken()).thenReturn(TOKEN);
        when(amexExpressCheckoutCard.getImageUrl()).thenReturn(IMAGE_URL);
        when(amexExpressCheckoutCard.isDefault()).thenReturn(IS_DEFAULT);
        when(amexExpressCheckoutCard.getBin()).thenReturn(BIN);
        when(amexExpressCheckoutCard.getUpdatedAt()).thenReturn(calendar);
        when(amexExpressCheckoutCard.getCustomerId()).thenReturn(CUSTOMER_ID);
        when(amexExpressCheckoutCard.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(amexExpressCheckoutCard.getExpirationYear()).thenReturn(EXPIRATION_YEAR);

        unit.populate(amexExpressCheckoutCard, target);

        assertEquals(TOKEN, target.getPaymentMethodToken());
        assertEquals(IMAGE_URL, target.getImageSource());
        assertEquals(IS_DEFAULT, target.isIsDefault());
        assertEquals(BIN, target.getPaymentInfo());
        assertEquals(CUSTOMER_ID, target.getCustomerId());
        assertEquals(BrainTreePaymentMethod.AMEXEXPRESSCHECKOUTCARD.getCode(), target.getPaymentProvider());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());
    }
}