package com.braintree.populators;

import com.braintree.servicelayer.i18n.BraintreeRegionI18NService;
import com.braintreegateway.Address;
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 de.hybris.platform.servicelayer.i18n.CommonI18NService;
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 static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

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

    private static final String REGION = "Region";
    private static final String COUNTRY_CODE_ALPHA_3 = "CountryCodeAlpha3";
    private static final String COUNTRY_CODE_ALPHA_2 = "CountryCodeAlpha2";
    private static final String STREET_ADDRESS = "StreetAddress";
    private static final String EXTENDED_ADDRESS = "ExtendedAddress";
    private static final String COMPANY = "Company";
    private static final String FIRST_NAME = "User";
    private static final String LAST_NAME = "Tester";
    private static final String LOCALITY = "Locality";
    private static final String POSTAL_CODE = "PostalCode";

    @InjectMocks
    private BraintreeAddressPopulator unit;

    @Mock
    private BraintreeRegionI18NService regionI18NService;
    @Mock
    private CommonI18NService commonI18NService;
    @Mock
    private CountryModel countryModel;
    @Mock
    private CountryModel countryModelAlpha3;
    @Mock
    private RegionModel regionModel;

    @Mock
    Address address;

    @Before
    public void setUp(){
        when(address.getCountryCodeAlpha2()).thenReturn(COUNTRY_CODE_ALPHA_2);
        when(address.getCountryCodeAlpha3()).thenReturn(COUNTRY_CODE_ALPHA_3);
        when(address.getRegion()).thenReturn(REGION);
        when(address.getStreetAddress()).thenReturn(STREET_ADDRESS);
        when(address.getExtendedAddress()).thenReturn(EXTENDED_ADDRESS);
        when(address.getCompany()).thenReturn(COMPANY);
        when(address.getFirstName()).thenReturn(FIRST_NAME);
        when(address.getLastName()).thenReturn(LAST_NAME);
        when(address.getLocality()).thenReturn(LOCALITY);
        when(address.getPostalCode()).thenReturn(POSTAL_CODE);
    }

    @Test
    public void shouldPopulateAddressToAddressModelWithAlpha2Test(){
        AddressModel target = new AddressModel();

        when(commonI18NService.getCountry(COUNTRY_CODE_ALPHA_2)).thenReturn(countryModel);
        when(regionI18NService.findRegion(countryModel, REGION)).thenReturn(regionModel);

        unit.populate(address, target);

        assertEquals(countryModel, target.getCountry());
        assertEquals(regionModel, target.getRegion());
        verifyAddress(target);
    }

    @Test
    public void shouldPopulateAddressToAddressModelWithAlpha3Test(){
        AddressModel target = new AddressModel();

        when(commonI18NService.getCountry(COUNTRY_CODE_ALPHA_3)).thenReturn(countryModelAlpha3);
        when(regionI18NService.findRegion(countryModelAlpha3, REGION)).thenReturn(regionModel);

        unit.populate(address, target);

        assertEquals(countryModelAlpha3, target.getCountry());
        assertEquals(regionModel, target.getRegion());
        verifyAddress(target);
    }

    @Test
    public void shouldDoNothingWhenAddressIsNull(){
        AddressModel target = new AddressModel();

        unit.populate(null, target);

        verify(address, never()).getFirstName();
    }

    @Test
    public void shouldDoNothingWhenModelIsNull(){
        unit.populate(address, null);

        verify(address, never()).getFirstName();
    }

    private void verifyAddress(AddressModel target){
        assertEquals(REGION, target.getZone());
        assertEquals(STREET_ADDRESS, target.getStreetname());
        assertEquals(EXTENDED_ADDRESS, target.getStreetnumber());
        assertEquals(COMPANY, target.getCompany());
        assertEquals(FIRST_NAME, target.getFirstname());
        assertEquals(LAST_NAME, target.getLastname());
        assertEquals(LOCALITY, target.getTown());
        assertEquals(POSTAL_CODE, target.getPostalcode());
    }
}
