package com.braintree.customersupportbackoffice.handler;

import com.braintree.enums.BraintreeThreeDSecureFlow;
import com.braintree.enums.BraintreeThreeDSecureSCAExemptionType;
import com.hybris.cockpitng.dataaccess.facades.object.ObjectFacade;
import com.hybris.cockpitng.engine.WidgetInstanceManager;
import com.hybris.cockpitng.util.notifications.NotificationService;
import com.hybris.cockpitng.util.notifications.event.NotificationEvent;
import com.hybris.cockpitng.validation.ValidationContext;
import com.hybris.cockpitng.validation.model.ValidationInfo;
import com.hybris.cockpitng.validation.model.ValidationSeverity;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.model.BraintreeGeneralConfigurationModel;
import de.hybris.platform.servicelayer.model.ModelService;
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.List;

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;


@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class BraintreeGeneralConfigurationLogicHandlerTest {
    private static final String SUBMIT_FOR_SETTLEMENT_DISABLED = "submitForSettlementDisabled";
    private static final String VAULT_FLOW_ENABLED = "vaultFlowEnabled";
    private static final String BRAINTREE_THREEDSECURE_FLOW_DISABLED = "braintreeThreeDSecureFlowDisabled";
    private static final String BRAINTREE_CHALLENGE_REQUESTED_AND_SCA_EXAMPTION_ENABLED = "SCA Exemption and Challenge Requested cannot be enabled simultaneously";
    @Mock
    private NotificationService notificationService;
    @Mock
    private ObjectFacade objectFacade;
    @Mock
    private WidgetInstanceManager widgetInstanceManager;
    @Mock
    private ModelService modelService;
    @Mock
    private ValidationContext validationContext;
    @Mock
    private BraintreeGeneralConfigurationModel braintreeGeneralConfigurationModel;
    @Mock
    private BraintreeGeneralConfigurationModel originalConfiguration;
    @InjectMocks
    private BraintreeGeneralConfigurationLogicHandler unit;
    @Test
    public void shouldPerformSaveWhenSubmitForSettlementIsTrueDisabled() throws Exception {
        when(originalConfiguration.isSubmitForSettlement()).thenReturn(true);
        when(braintreeGeneralConfigurationModel.isSubmitForSettlement()).thenReturn(false);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService).notifyUser(widgetInstanceManager, SUBMIT_FOR_SETTLEMENT_DISABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldNotPerformSaveWhenSubmitForSettlementIsFalse() throws Exception {
        when(originalConfiguration.isSubmitForSettlement()).thenReturn(false);
        when(braintreeGeneralConfigurationModel.isSubmitForSettlement()).thenReturn(false);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService, never()).notifyUser(widgetInstanceManager, SUBMIT_FOR_SETTLEMENT_DISABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldPerformSaveWhenStoreInVaultEnabled() throws Exception {
        when(originalConfiguration.isSubmitForSettlement()).thenReturn(false);
        when(braintreeGeneralConfigurationModel.isStoreInVault()).thenReturn(true);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService).notifyUser(widgetInstanceManager, VAULT_FLOW_ENABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldNotPerformSaveWhenStoreInVaultDisabled() throws Exception {
        when(originalConfiguration.isSubmitForSettlement()).thenReturn(false);
        when(braintreeGeneralConfigurationModel.isStoreInVault()).thenReturn(false);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService, never()).notifyUser(widgetInstanceManager, VAULT_FLOW_ENABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldPerformSaveWhenThreeDSecureIsDisabledAndThreeDSecureSCAExemptionEqualsLowValue() throws Exception {
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureFlow()).thenReturn(BraintreeThreeDSecureFlow.DISABLED);
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption()).thenReturn(BraintreeThreeDSecureSCAExemptionType.LOW_VALUE);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService).notifyUser(widgetInstanceManager, BRAINTREE_THREEDSECURE_FLOW_DISABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldPerformSaveWhenThreeDSecureIsDisabledAndThreeDSecureSCAExemptionEqualsTransactionRiskAnalysis() throws Exception {
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureFlow()).thenReturn(BraintreeThreeDSecureFlow.DISABLED);
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption()).thenReturn(BraintreeThreeDSecureSCAExemptionType.TRANSACTION_RISK_ANALYSIS);
        when(modelService.get(braintreeGeneralConfigurationModel.getPk())).thenReturn(originalConfiguration);
        unit.performSave(widgetInstanceManager,braintreeGeneralConfigurationModel);
        verify(notificationService).notifyUser(widgetInstanceManager, BRAINTREE_THREEDSECURE_FLOW_DISABLED,
                NotificationEvent.Level.INFO);
    }

    @Test
    public void shouldPerformperformValidationWhenChallengeRequestedAndSCAExemptionEnabled() throws Exception {
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption()).thenReturn(BraintreeThreeDSecureSCAExemptionType.TRANSACTION_RISK_ANALYSIS);
        when(braintreeGeneralConfigurationModel.isBraintreeThreeDSecureChallengeRequested()).thenReturn(true);

        List<ValidationInfo> validationInfo = unit.performValidation(widgetInstanceManager,braintreeGeneralConfigurationModel, validationContext);

        assertNotNull(validationInfo);
        assertEquals(validationInfo.get(0).getValidationSeverity(), ValidationSeverity.ERROR);
        assertEquals(validationInfo.get(0).getValidationMessage(), BRAINTREE_CHALLENGE_REQUESTED_AND_SCA_EXAMPTION_ENABLED);
    }

    @Test
    public void shouldPerformperformValidationWhenSCAExemptionEnabled() throws Exception {
        when(braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption()).thenReturn(BraintreeThreeDSecureSCAExemptionType.TRANSACTION_RISK_ANALYSIS);
        when(braintreeGeneralConfigurationModel.isBraintreeThreeDSecureChallengeRequested()).thenReturn(false);

        List<ValidationInfo> validationInfo = unit.performValidation(widgetInstanceManager,braintreeGeneralConfigurationModel, validationContext);

        assertNotNull(validationInfo);
        assertEquals(validationInfo.get(0).getValidationSeverity(), ValidationSeverity.NONE);
        assertNull(validationInfo.get(0).getValidationMessage());
    }
}
