package com.braintree.util;

import com.braintree.command.result.BrainTreeBillingAddressResult;
import com.braintree.command.result.BrainTreePaymentDetailsResult;
import com.braintree.enums.BrainTreeCardType;
import com.braintree.hybris.data.BrainTreeSubscriptionInfoData;
import com.braintree.model.BrainTreePaymentInfoModel;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.c2l.CountryModel;
import de.hybris.platform.core.model.c2l.RegionModel;
import de.hybris.platform.core.model.user.AddressModel;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

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

    private static final BrainTreeCardType cardType = BrainTreeCardType.VISA;
    private static final String EMAIL = "EMAIL";
    private static final String US = "US";
    private static final String EU = "EU";
    private static final String LAST_4 = "1111";
    private static final String ROUTING_NUMBER = "ROUTING_NUMBER";

    @Mock
    private BrainTreePaymentDetailsResult oldPaymentData;
    @Mock
    private BrainTreeSubscriptionInfoData newPaymentData;
    @Mock
    private BrainTreePaymentInfoModel oldPaymentModel;
    @Mock
    private BrainTreePaymentInfoModel newPaymentModel;
    @Mock
    private RegionModel oldRegion;
    @Mock
    private RegionModel newRegion;

    @Test
    public void shouldReturnTrueForEmailBasedCheckData() {
        when(oldPaymentData.getEmail()).thenReturn(EMAIL);
        when(newPaymentData.getEmail()).thenReturn(EMAIL);

        assertTrue(BrainTreeDuplicateCheckUtils.emailBasedCheck(oldPaymentData, newPaymentData));
    }

    @Test
    public void shouldReturnTrueForEmailBasedCheckModel() {
        when(oldPaymentModel.getPayer()).thenReturn(EMAIL);
        when(newPaymentModel.getPayer()).thenReturn(EMAIL);

        assertTrue(BrainTreeDuplicateCheckUtils.emailBasedCheck(oldPaymentModel, newPaymentModel));
    }

    @Test
    public void checkForGoogleAndSrcData() {
        when(oldPaymentData.getCardType()).thenReturn(cardType.toString());
        when(newPaymentData.getCardType()).thenReturn(cardType.toString());
        when(oldPaymentData.getEmail()).thenReturn(EMAIL);
        when(newPaymentData.getEmail()).thenReturn(EMAIL);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForGoogleAndSrc(oldPaymentData, newPaymentData));
    }

    @Test
    public void checkForGoogleAndSrcModel() {
        when(oldPaymentModel.getCardType()).thenReturn(cardType);
        when(newPaymentModel.getCardType()).thenReturn(cardType);
        when(oldPaymentModel.getPayer()).thenReturn(EMAIL);
        when(newPaymentModel.getPayer()).thenReturn(EMAIL);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForGoogleAndSrc(oldPaymentModel, newPaymentModel));
    }

    @Test
    public void shouldReturnTrueForCheckRegionString() {
        when(newRegion.getIsocodeShort()).thenReturn(US);

        assertTrue(BrainTreeDuplicateCheckUtils.checkRegion(US, newRegion));
    }

    @Test
    public void shouldReturnFalseBecauseRegionsAreDifferentString() {
        when(newRegion.getIsocodeShort()).thenReturn(EU);

        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion(US, newRegion));
    }

    @Test
    public void shouldReturnTrueBecauseAllRegionsAreNullForCheckRegionString() {
        assertTrue(BrainTreeDuplicateCheckUtils.checkRegion((String) null, null));
    }

    @Test
    public void shouldReturnFalseBecauseFirstRegionIsNullForCheckRegionString() {
        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion((String) null, newRegion));
    }

    @Test
    public void shouldReturnFalseBecauseSecondRegionIsNullForCheckRegionString() {
        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion(US, null));
    }

    @Test
    public void shouldReturnTrueForCheckRegionObject() {
        when(oldRegion.getIsocodeShort()).thenReturn(US);
        when(newRegion.getIsocodeShort()).thenReturn(US);

        assertTrue(BrainTreeDuplicateCheckUtils.checkRegion(oldRegion, newRegion));
    }

    @Test
    public void shouldReturnFalseBecauseRegionsAreDifferentObject() {
        when(oldRegion.getIsocodeShort()).thenReturn(US);
        when(newRegion.getIsocodeShort()).thenReturn(EU);

        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion(oldRegion, newRegion));
    }

    @Test
    public void shouldReturnTrueBecauseAllRegionsAreNullForCheckRegionObject() {
        assertTrue(BrainTreeDuplicateCheckUtils.checkRegion((RegionModel) null, null));
    }

    @Test
    public void shouldReturnFalseBecauseFirstRegionIsNullForCheckRegionObject() {
        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion((RegionModel) null, newRegion));
    }

    @Test
    public void shouldReturnFalseBecauseSecondRegionIsNullForCheckRegionObject() {
        assertFalse(BrainTreeDuplicateCheckUtils.checkRegion(oldRegion, null));
    }

    @Test
    public void shouldReturnTrueForCheckForCreditCardData() {
        AddressModel newBillingAddress = mock(AddressModel.class);
        BrainTreeBillingAddressResult billingAddressResult = mock(BrainTreeBillingAddressResult.class);

        when(oldPaymentData.getCardType()).thenReturn(cardType.toString());
        when(newPaymentData.getCardType()).thenReturn(cardType.toString());

        when(oldPaymentData.getBillingAddress()).thenReturn(billingAddressResult);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForCreditCard(oldPaymentData, newPaymentData, newBillingAddress));
    }

    @Test
    public void shouldReturnTrueForCheckForCreditCardModel() {
        AddressModel newBillingAddress = mock(AddressModel.class);
        AddressModel oldBillingAddress = mock(AddressModel.class);
        CountryModel oldCountry = mock(CountryModel.class);
        CountryModel newCountry = mock(CountryModel.class);


        when(oldPaymentModel.getCardType()).thenReturn(cardType);
        when(newPaymentModel.getCardType()).thenReturn(cardType);

        when(oldPaymentModel.getBillingAddress()).thenReturn(oldBillingAddress);

        when(oldBillingAddress.getCountry()).thenReturn(oldCountry);
        when(newBillingAddress.getCountry()).thenReturn(newCountry);

        when(oldCountry.getIsocode()).thenReturn(US);
        when(newCountry.getIsocode()).thenReturn(US);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForCreditCard(oldPaymentModel, newPaymentModel, newBillingAddress));
    }

    @Test
    public void shouldReturnTrueForCheckForUsBankAccountData() {
        when(oldPaymentData.getLast4()).thenReturn(LAST_4);
        when(newPaymentData.getLast4()).thenReturn(LAST_4);

        when(oldPaymentData.getRoutingNumber()).thenReturn(ROUTING_NUMBER);
        when(newPaymentData.getRoutingNumber()).thenReturn(ROUTING_NUMBER);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentData, newPaymentData));
    }

    @Test
    public void shouldReturnFalseBecauseOneLast4IsNotCorrectForUsBankAccountData() {
        when(oldPaymentData.getLast4()).thenReturn(LAST_4);
        when(newPaymentData.getLast4()).thenReturn(StringUtils.EMPTY);

        assertFalse(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentData, newPaymentData));
    }

    @Test
    public void shouldReturnFalseBecauseOneRoutingNumberIsNotCorrectForUsBankAccountData() {
        when(oldPaymentData.getLast4()).thenReturn(LAST_4);
        when(newPaymentData.getLast4()).thenReturn(LAST_4);

        when(oldPaymentData.getRoutingNumber()).thenReturn(ROUTING_NUMBER);
        when(newPaymentData.getRoutingNumber()).thenReturn(StringUtils.EMPTY);

        assertFalse(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentData, newPaymentData));
    }

    @Test
    public void shouldReturnTrueForCheckForUsBankAccountModel() {
        when(oldPaymentModel.getLast4()).thenReturn(LAST_4);
        when(newPaymentModel.getLast4()).thenReturn(LAST_4);

        when(oldPaymentModel.getRoutingNumber()).thenReturn(ROUTING_NUMBER);
        when(newPaymentModel.getRoutingNumber()).thenReturn(ROUTING_NUMBER);

        assertTrue(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentModel, newPaymentModel));
    }

    @Test
    public void shouldReturnFalseBecauseOneLast4IsNotCorrectForUsBankAccountModel() {
        when(oldPaymentModel.getLast4()).thenReturn(LAST_4);
        when(newPaymentModel.getLast4()).thenReturn(StringUtils.EMPTY);

        assertFalse(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentModel, newPaymentModel));
    }

    @Test
    public void shouldReturnFalseBecauseOneRoutingNumberIsNotCorrectForUsBankAccountModel() {
        when(oldPaymentModel.getLast4()).thenReturn(LAST_4);
        when(newPaymentModel.getLast4()).thenReturn(LAST_4);

        when(oldPaymentModel.getRoutingNumber()).thenReturn(ROUTING_NUMBER);
        when(newPaymentModel.getRoutingNumber()).thenReturn(StringUtils.EMPTY);

        assertFalse(BrainTreeDuplicateCheckUtils.checkForUsBankAccount(oldPaymentModel, newPaymentModel));
    }

}
