package com.braintree.populators;

import com.braintree.command.result.BrainTreeBillingAddressResult;
import com.braintree.enums.BrainTreeCardType;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeAddress;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeCustomer;
import com.braintree.hybris.data.graphql.commands.response.BraintreePaymentMethodData;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodDetails;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodOrigin;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.payment.info.service.BraintreePaymentInfoService;
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.Before;
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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;

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

    private static final String ORIGIN_TYPE = "OriginType";
    private static final String ID = "Id";
    private static final String LEGACY_ID = "LegacyId";
    private static final String TYPE_NAME = "TypeName";
    private static final String PAYMENT_PROVIDER = "PaymentProvider";
    private static final String BRAND_CODE = "MasterCard";
    private static final String IMAGE_SOURCE = "ImageSource";
    private static final String LAST_FOUR = "1234";
    private static final String BIN = "4111";
    private static final String CARD_NUMBER = "4111******1234";
    private static final String CUSTOMER_ID = "CustomerId";
    private static final String EXPIRATION_MONTH = "ExpirationMonth";
    private static final String EXPIRATION_YEAR = "ExpirationYear";
    private static final String CARD_HOLDER_NAME = "CardHolderName";

    @InjectMocks
    private BraintreePaymentMethodDetailsToModelPopulator unit;

    @Mock
    private BraintreePaymentInfoService braintreePaymentInfoService;
    @Mock
    private Converter<BrainTreeAddress, BrainTreeBillingAddressResult> graphQLAddressToAddressResult;
    @Mock
    private Converter<BrainTreeBillingAddressResult, AddressModel> addressResultToAddressModelConverter;
    @Mock
    private BraintreePaymentMethodData brainTreePaymentMethod;
    @Mock
    private BrainTreePaymentMethodDetails paymentMethodDetails;
    @Mock
    private BrainTreePaymentMethodOrigin brainTreePaymentMethodOrigin;
    @Mock
    private Calendar calendar;
    @Mock
    private BrainTreeCustomer customer;
    @Mock
    private BrainTreeAddress brainTreeBillingAddress;
    @Mock
    private BrainTreeBillingAddressResult billingAddressResult;
    @Mock
    private AddressModel billingAddressModel;

    @Before
    public void setUp(){
        when(brainTreePaymentMethod.getLegacyId()).thenReturn(LEGACY_ID);
        when(brainTreePaymentMethod.getId()).thenReturn(ID);
        when(brainTreePaymentMethod.getDetails()).thenReturn(paymentMethodDetails);
        when(paymentMethodDetails.getOrigin()).thenReturn(brainTreePaymentMethodOrigin);
        when(brainTreePaymentMethodOrigin.getType()).thenReturn(ORIGIN_TYPE);
        when(paymentMethodDetails.get__typename()).thenReturn(TYPE_NAME);
        when(braintreePaymentInfoService.getPaymentProviderByDetailsAndOrigin(TYPE_NAME, ORIGIN_TYPE)).thenReturn(PAYMENT_PROVIDER);
        when(paymentMethodDetails.getBrandCode()).thenReturn(BRAND_CODE);
        when(braintreePaymentInfoService.getImageSourceByPaymentProviderAndCardType(PAYMENT_PROVIDER, BRAND_CODE)).thenReturn(IMAGE_SOURCE);
        when(paymentMethodDetails.getLast4()).thenReturn(LAST_FOUR);
        when(paymentMethodDetails.getBin()).thenReturn(BIN);
        when(brainTreePaymentMethod.getCreatedAt()).thenReturn(calendar);
        when(brainTreePaymentMethod.getCustomer()).thenReturn(customer);
        when(customer.getLegacyId()).thenReturn(CUSTOMER_ID);
        when(paymentMethodDetails.getCardholderName()).thenReturn(CARD_HOLDER_NAME);
        when(paymentMethodDetails.getExpirationMonth()).thenReturn(EXPIRATION_MONTH);
        when(paymentMethodDetails.getExpirationYear()).thenReturn(EXPIRATION_YEAR);
        when(paymentMethodDetails.getBillingAddress()).thenReturn(brainTreeBillingAddress);
        when(graphQLAddressToAddressResult.convert(brainTreeBillingAddress)).thenReturn(billingAddressResult);
        when(addressResultToAddressModelConverter.convert(billingAddressResult)).thenReturn(billingAddressModel);
    }

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

        unit.populate(brainTreePaymentMethod, target);

        assertEquals(LEGACY_ID, target.getPaymentMethodToken());
        assertEquals(ID, target.getPaymentMethodGraphQLToken());
        assertEquals(PAYMENT_PROVIDER, target.getPaymentProvider());
        assertEquals(IMAGE_SOURCE, target.getImageSource());
        assertEquals(CARD_NUMBER, target.getPaymentInfo());
        assertEquals(CARD_NUMBER, target.getCardNumber());
        assertEquals(calendar.getTime(), target.getCreatedAt());
        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(billingAddressModel, target.getBillingAddress());
    }

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

        when(paymentMethodDetails.getOrigin()).thenReturn(null);
        when(paymentMethodDetails.getBin()).thenReturn(null);
        when(brainTreePaymentMethod.getCustomer()).thenReturn(null);
        when(paymentMethodDetails.getBrandCode()).thenReturn(null);
        when(paymentMethodDetails.getBillingAddress()).thenReturn(null);

        unit.populate(brainTreePaymentMethod, target);

        assertEquals(LEGACY_ID, target.getPaymentMethodToken());
        assertEquals(ID, target.getPaymentMethodGraphQLToken());
        assertEquals(calendar.getTime(), target.getCreatedAt());
        assertEquals(CARD_HOLDER_NAME, target.getCardholderName());
        assertEquals(EXPIRATION_MONTH, target.getExpirationMonth());
        assertEquals(EXPIRATION_YEAR, target.getExpirationYear());

        assertNull(target.getPaymentProvider());
        assertNull(target.getImageSource());
        assertNull(target.getPaymentInfo());
        assertNull(target.getCardNumber());
        assertNull(target.getCustomerId());
        assertNull(target.getCardType());
        assertNull(target.getBillingAddress());

    }
}
