package com.braintree.converters;

import com.braintree.hybris.data.PayPalAddressData;
import com.braintree.paypal.validator.BraintreePayPalAddressDetailValidator;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.commercefacades.user.data.CountryData;
import de.hybris.platform.commercefacades.user.data.RegionData;
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 de.hybris.platform.core.model.user.TitleModel;
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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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

    private static final String FIRST_NAME = "firstName";
    private static final String LAST_NAME = "lastName";
    private static final String TITLE_NAME = "titleName";
    private static final String TOWN = "town";
    private static final String PHONE = "phone";
    private static final String POSTAL_CODE = "postalCode";
    private static final String LINE_1 = "line1";
    private static final String LINE_2 = "line2";
    private static final String REGION_ISOCODE = "regionIsocode";
    private static final String COUNTRY_ISOCODE = "countryIsocode";
    private static final String PERSONAL = "Personal";
    private static final String CITY = "city";

    @Mock
    private AddressModel model;
    @Mock
    private TitleModel titleModel;
    @Mock
    private RegionModel regionModel;
    @Mock
    private CountryModel countryModel;

    @Mock
    private BraintreePayPalAddressDetailValidator payPalAddressDetailValidator;
    @InjectMocks
    @Spy
    private BrainTreePayPalAddressDataConverter unit;

    @Test
    public void shouldConverAddressModelToPayPalAddressData() {
        PayPalAddressData data = new PayPalAddressData();

        when(model.getFirstname()).thenReturn(FIRST_NAME);
        when(model.getLastname()).thenReturn(LAST_NAME);
        when(model.getTitle()).thenReturn(titleModel);
        when(titleModel.getName()).thenReturn(TITLE_NAME);
        when(model.getTown()).thenReturn(TOWN);
        when(model.getPhone1()).thenReturn(PHONE);
        when(model.getPostalcode()).thenReturn(POSTAL_CODE);
        when(model.getLine1()).thenReturn(LINE_1);
        when(model.getLine2()).thenReturn(LINE_2);
        when(model.getRegion()).thenReturn(regionModel);
        when(regionModel.getIsocodeShort()).thenReturn(REGION_ISOCODE);
        when(model.getCountry()).thenReturn(countryModel);
        when(countryModel.getIsocode()).thenReturn(COUNTRY_ISOCODE);

        PayPalAddressData result = unit.convert(model, data);

        assertEquals(data, result);
        assertEquals(TOWN, result.getLocality());
        assertEquals(PHONE, result.getPhone());
        assertEquals(POSTAL_CODE, result.getPostalCode());
        assertEquals(String.format("%s %s %s", TITLE_NAME, FIRST_NAME, LAST_NAME), result.getRecipientName());
        assertEquals(LINE_1, result.getStreetAddress());
        assertEquals(LINE_2, result.getExtendedAddress());
        assertEquals(PERSONAL, result.getType());
        assertEquals(REGION_ISOCODE, result.getRegion());
        assertEquals(COUNTRY_ISOCODE, result.getCountryCodeAlpha2());
    }

    @Test
    public void shouldConverAddressModelToPayPalAddressDataAndCreateNewObject() {
        when(model.getFirstname()).thenReturn(FIRST_NAME);
        when(model.getLastname()).thenReturn(LAST_NAME);
        when(model.getTitle()).thenReturn(titleModel);
        when(titleModel.getName()).thenReturn(TITLE_NAME);
        when(model.getTown()).thenReturn(TOWN);
        when(model.getPhone1()).thenReturn(PHONE);
        when(model.getPostalcode()).thenReturn(POSTAL_CODE);
        when(model.getLine1()).thenReturn(LINE_1);
        when(model.getLine2()).thenReturn(LINE_2);
        when(model.getRegion()).thenReturn(regionModel);
        when(regionModel.getIsocodeShort()).thenReturn(REGION_ISOCODE);
        when(model.getCountry()).thenReturn(countryModel);
        when(countryModel.getIsocode()).thenReturn(COUNTRY_ISOCODE);


        PayPalAddressData result = unit.convert(model);

        verify(unit).convert(eq(model), any(PayPalAddressData.class));

        assertEquals(TOWN, result.getLocality());
        assertEquals(PHONE, result.getPhone());
        assertEquals(POSTAL_CODE, result.getPostalCode());
        assertEquals(String.format("%s %s %s", TITLE_NAME, FIRST_NAME, LAST_NAME), result.getRecipientName());
        assertEquals(LINE_1, result.getStreetAddress());
        assertEquals(LINE_2, result.getExtendedAddress());
        assertEquals(PERSONAL, result.getType());
        assertEquals(REGION_ISOCODE, result.getRegion());
        assertEquals(COUNTRY_ISOCODE, result.getCountryCodeAlpha2());
    }

    @Test
    public void shouldConvertPayPalAddressDataToAddressData() {
        PayPalAddressData data = new PayPalAddressData();
        data.setCountryCode(COUNTRY_ISOCODE);
        data.setState(REGION_ISOCODE);
        data.setLine1(LINE_1);
        data.setLine2(LINE_2);
        data.setPhone(PHONE);
        data.setPostalCode(POSTAL_CODE);
        data.setRecipientName(String.format("%s %s", FIRST_NAME, LAST_NAME));
        data.setCity(CITY);

        when(payPalAddressDetailValidator.validatePayPalCountryCode(COUNTRY_ISOCODE)).thenReturn(true);
        when(payPalAddressDetailValidator.validatePayPalRegionCode(COUNTRY_ISOCODE, REGION_ISOCODE)).thenReturn(true);

        AddressData result = unit.convert(data);
        CountryData resultCountry = result.getCountry();
        RegionData resultRegion = result.getRegion();

        assertEquals(COUNTRY_ISOCODE, resultCountry.getIsocode());
        assertEquals(String.format("%s-%s", COUNTRY_ISOCODE, REGION_ISOCODE), resultRegion.getIsocode());
        assertEquals(LINE_1, result.getLine1());
        assertEquals(LINE_2, result.getLine2());
        assertEquals(PHONE, result.getPhone());
        assertEquals(POSTAL_CODE, result.getPostalCode());
        assertEquals(FIRST_NAME, result.getFirstName());
        assertEquals(LAST_NAME, result.getLastName());
        assertEquals(CITY, result.getTown());
    }

    @Test
    public void shouldConvertPayPalAddressDataToAddressDataWithSomeNullValues() {
        when(model.getFirstname()).thenReturn(FIRST_NAME);
        when(model.getLastname()).thenReturn(LAST_NAME);
        when(model.getTitle()).thenReturn(null);
        when(model.getTown()).thenReturn(TOWN);
        when(model.getPhone1()).thenReturn(PHONE);
        when(model.getPostalcode()).thenReturn(POSTAL_CODE);
        when(model.getLine1()).thenReturn(LINE_1);
        when(model.getLine2()).thenReturn(LINE_2);
        when(model.getRegion()).thenReturn(null);
        when(model.getCountry()).thenReturn(null);


        PayPalAddressData result = unit.convert(model);

        verify(unit).convert(eq(model), any(PayPalAddressData.class));

        assertNull(result.getRegion());
        assertNull(result.getCountryCodeAlpha2());
    }
}
