package com.braintree.interceptors;

import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.BraintreeGeneralConfigurationModel;
import de.hybris.platform.servicelayer.interceptor.InterceptorContext;
import de.hybris.platform.servicelayer.interceptor.InterceptorException;
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.assertThrows;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;

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

    private static final String CORRECT_PRODUCT_NAME = "name-";
    private static final String CORRECT_BUSINESS_NAME = "BT-";
    private static final String CORRECT_PHONE_NUMBER = "(123)4567890";
    private static final String CORRECT_URL = "url.mail.com";
    private static final String WRONG_BUSINESS_NAME = "BT@_";
    private static final String WRONG_PRODUCT_NAME = "productNameWhichWrong_";
    private static final String WRONG_PHONE_NUMBER = "12345";
    private static final String WRONG_PHONE_NUMBER_WITH_11_DIGIT = "12345678901";
    private static final String WRONG_PHONE_NUMBER_WITH_5_SPECIFIC_CHAR = "1234567890()---";
    private static final String WRONG_URL = "urlWhichISWrong.@gmail.com";
    private static final String THROWN_EXCEPTION_ERROR_MSG = "Should not fail on passed validation";

    @Mock
    BraintreeGeneralConfigurationModel config;
    @Mock
    InterceptorContext ctx;

    @InjectMocks
    BrainTreeGeneralConfigurationValidationInterceptor validationInterceptor;


    @Test
    public void shouldNotThrowAnExceptionWhenCorrectConfiguration() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(CORRECT_PRODUCT_NAME);
        when(config.getDescriptorPhoneNumber()).thenReturn(CORRECT_PHONE_NUMBER);
        when(config.getDescriptorUrl()).thenReturn(CORRECT_URL);

        try {

            validationInterceptor.onValidate(config, ctx);

        } catch (InterceptorException exception) {
            fail(THROWN_EXCEPTION_ERROR_MSG);
        }
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongURL() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(CORRECT_PRODUCT_NAME);
        when(config.getDescriptorPhoneNumber()).thenReturn(CORRECT_PHONE_NUMBER);
        when(config.getDescriptorUrl()).thenReturn(WRONG_URL);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }

    @Test
    public void shouldNotThrowAnExceptionWhenValuesIsNull() {
        when(config.getDescriptorBusinessName()).thenReturn(null);
        when(config.getDescriptorProductName()).thenReturn(null);
        when(config.getDescriptorPhoneNumber()).thenReturn(null);
        when(config.getDescriptorUrl()).thenReturn(null);

        try {
            validationInterceptor.onValidate(config, ctx);
        } catch (InterceptorException exception) {
            fail(THROWN_EXCEPTION_ERROR_MSG);
        }
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongBusinessName() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(WRONG_BUSINESS_NAME);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongProductName() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(WRONG_PRODUCT_NAME);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongPhoneNumber() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(CORRECT_PRODUCT_NAME);
        when(config.getDescriptorPhoneNumber()).thenReturn(WRONG_PHONE_NUMBER);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongPhoneNumberWithOver10Digit() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(CORRECT_PRODUCT_NAME);
        when(config.getDescriptorPhoneNumber()).thenReturn(WRONG_PHONE_NUMBER_WITH_11_DIGIT);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }

    @Test
    public void shouldThrowAnExceptionWhenWrongPhoneNumberWithOverFourSpecificChar() throws InterceptorException {
        when(config.getDescriptorBusinessName()).thenReturn(CORRECT_BUSINESS_NAME);
        when(config.getDescriptorProductName()).thenReturn(CORRECT_PRODUCT_NAME);
        when(config.getDescriptorPhoneNumber()).thenReturn(WRONG_PHONE_NUMBER_WITH_5_SPECIFIC_CHAR);

        assertThrows(InterceptorException.class, () -> {
            validationInterceptor.onValidate(config,ctx);
        });
    }
}
