package com.braintree.customersupportbackoffice.handler;

import com.braintree.enums.BraintreeThreeDSecureFlow;
import com.braintree.enums.BraintreeThreeDSecureSCAExemptionType;
import com.hybris.backoffice.editorarea.BackofficeEditorAreaLogicHandler;
import com.hybris.cockpitng.dataaccess.facades.object.exceptions.ObjectSavingException;
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.impl.DefaultValidationInfo;
import com.hybris.cockpitng.validation.model.ValidationInfo;
import com.hybris.cockpitng.validation.model.ValidationSeverity;
import de.hybris.platform.core.model.BraintreeGeneralConfigurationModel;
import de.hybris.platform.servicelayer.model.ModelService;

import java.util.List;

public class BraintreeGeneralConfigurationLogicHandler extends BackofficeEditorAreaLogicHandler {
    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_THREEDSECURE_SCA_EXEMPTION = "braintreeThreeDSecureSCAExemption";
    private static final String BRAINTREE_THREEDSECURE_DISABLED = "braintreeThreeDSecureDisabled";
    private static final String BRAINTREE_REPLENISHMENT_WARNING = "braintreeReplenishmentWarning";
    private static final String BRAINTREE_SCA_EXEMPTION_INACTIVE = "braintreeSCAExemptionInactive";
    private static final String BRAINTREE_CHALLENGE_REQUESTED_INACTIVE = "braintreeChallengeRequestedInactive";
    private static final String BRAINTREE_CHALLENGE_REQUESTED_AND_SCA_EXAMPTION_ENABLED = "SCA Exemption and Challenge Requested cannot be enabled simultaneously";

    private NotificationService notificationService;
    private ModelService modelService;

    @Override
    public Object performSave(WidgetInstanceManager widgetInstanceManager, Object currentObject) throws ObjectSavingException {
        BraintreeGeneralConfigurationModel braintreeGeneralConfigurationModel = (BraintreeGeneralConfigurationModel) currentObject;
        if (isSubmitForSettlement(braintreeGeneralConfigurationModel)) {
            notificationService.notifyUser(widgetInstanceManager, SUBMIT_FOR_SETTLEMENT_DISABLED,
                    NotificationEvent.Level.INFO);
        }
        if (isStoreInVault(braintreeGeneralConfigurationModel)) {
            notificationService.notifyUser(widgetInstanceManager, VAULT_FLOW_ENABLED,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.getBraintreeThreeDSecureFlow() == BraintreeThreeDSecureFlow.DISABLED
                && braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption() != BraintreeThreeDSecureSCAExemptionType.DISABLED) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_THREEDSECURE_FLOW_DISABLED,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.getBraintreeThreeDSecureFlow() != BraintreeThreeDSecureFlow.DISABLED
                && braintreeGeneralConfigurationModel.isBraintreeThreeDSecureChallengeRequested()
                && braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption() != BraintreeThreeDSecureSCAExemptionType.DISABLED) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_THREEDSECURE_SCA_EXEMPTION,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.getBraintreeThreeDSecureFlow() == BraintreeThreeDSecureFlow.DISABLED) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_THREEDSECURE_DISABLED,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.isStoreInVault() &&
                braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption() != BraintreeThreeDSecureSCAExemptionType.DISABLED) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_REPLENISHMENT_WARNING,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.isBraintreeThreeDSecureChallengeRequested()) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_SCA_EXEMPTION_INACTIVE,
                    NotificationEvent.Level.INFO);
        }
        if (braintreeGeneralConfigurationModel.getBraintreeThreeDSecureSCAExemption() != BraintreeThreeDSecureSCAExemptionType.DISABLED) {
            notificationService.notifyUser(widgetInstanceManager, BRAINTREE_CHALLENGE_REQUESTED_INACTIVE,
                    NotificationEvent.Level.INFO);
        }

        return super.performSave(widgetInstanceManager, currentObject);
    }

    @Override
    public List<ValidationInfo> performValidation(final WidgetInstanceManager widgetInstanceManager, final Object currentObject,
                                                  final ValidationContext validationContext) {
        BraintreeGeneralConfigurationModel braintreeGeneralConfigurationModel = (BraintreeGeneralConfigurationModel) currentObject;
        final DefaultValidationInfo failedValidation = new DefaultValidationInfo();
        if (isChallengeRequestedAndSCAExemption(braintreeGeneralConfigurationModel)) {
            failedValidation.setValidationSeverity(ValidationSeverity.ERROR);
            failedValidation.setValidationMessage(BRAINTREE_CHALLENGE_REQUESTED_AND_SCA_EXAMPTION_ENABLED);

        } else {
            failedValidation.setValidationSeverity(ValidationSeverity.NONE);
        }

        return List.of(failedValidation);
    }

    private boolean isChallengeRequestedAndSCAExemption(BraintreeGeneralConfigurationModel configurationModel) {
        boolean challengeRequested = configurationModel.isBraintreeThreeDSecureChallengeRequested();
        BraintreeThreeDSecureSCAExemptionType scaExemption = configurationModel.getBraintreeThreeDSecureSCAExemption();

        return challengeRequested && (scaExemption == BraintreeThreeDSecureSCAExemptionType.TRANSACTION_RISK_ANALYSIS ||
                        scaExemption == BraintreeThreeDSecureSCAExemptionType.LOW_VALUE);
    }

    private boolean isSubmitForSettlement(BraintreeGeneralConfigurationModel braintreeGeneralConfigurationModel) {
        BraintreeGeneralConfigurationModel originalConfiguration = modelService.get(braintreeGeneralConfigurationModel.getPk());
        return !braintreeGeneralConfigurationModel.isSubmitForSettlement() && originalConfiguration.isSubmitForSettlement();
    }

    private boolean isStoreInVault(BraintreeGeneralConfigurationModel braintreeGeneralConfigurationModel) {
        BraintreeGeneralConfigurationModel originalConfiguration = modelService.get(braintreeGeneralConfigurationModel.getPk());
        return braintreeGeneralConfigurationModel.isStoreInVault() && !originalConfiguration.isStoreInVault();
    }

    public void setNotificationService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void setModelService(ModelService modelService) {
        this.modelService = modelService;
    }
}
