package com.braintree.workflows.actions;

import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.util.BrainTreeUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import de.hybris.platform.b2b.model.B2BCustomerModel;
import de.hybris.platform.b2b.model.B2BRegistrationModel;
import de.hybris.platform.b2bacceleratorservices.workflows.actions.AbstractAutomatedWorkflowTemplateJob;
import de.hybris.platform.core.model.order.payment.PaymentInfoModel;
import de.hybris.platform.core.model.user.AddressModel;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.servicelayer.interceptor.impl.InterceptorExecutionPolicy;
import de.hybris.platform.servicelayer.session.SessionExecutionBody;
import de.hybris.platform.servicelayer.session.SessionService;
import de.hybris.platform.servicelayer.user.PasswordEncoderConstants;
import de.hybris.platform.workflow.exceptions.WorkflowTerminatedException;
import de.hybris.platform.workflow.model.WorkflowActionModel;
import de.hybris.platform.workflow.model.WorkflowDecisionModel;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class PayPalRegistrationApprovedAutomatedWorkflowTemplateJob extends AbstractAutomatedWorkflowTemplateJob {

    private SessionService sessionService;

    @Override
    public WorkflowDecisionModel perform(WorkflowActionModel workflowAction) {
        final B2BRegistrationModel registration = getRegistrationAttachment(workflowAction);
        validateRegistrationUnit(registration);
        final CustomerModel customer = getCustomer(registration);

        final B2BCustomerModel b2BCustomer = createB2BCustomerModel(customer, registration);

        registration.setCustomer(b2BCustomer);

        getModelService().saveAll(b2BCustomer,registration);

        return defaultDecision(workflowAction);
    }

    private void validateRegistrationUnit(B2BRegistrationModel registration) {
        if (registration.getDefaultB2BUnit() == null) {
            throw new WorkflowTerminatedException("Default B2B unit is null!");
        }
    }

    protected B2BCustomerModel createB2BCustomerModel(final CustomerModel customer, final B2BRegistrationModel registration) {

        final B2BCustomerModel b2bCustomer = getModelService().create(B2BCustomerModel.class);

        b2bCustomer.setEmail(customer.getUid());
        b2bCustomer.setName(customer.getName());
        b2bCustomer.setTitle(customer.getTitle());
        b2bCustomer.setUid(customer.getUid());
        b2bCustomer.setPayPalPayerId(customer.getPayPalPayerId());
        b2bCustomer.setBraintreeCustomerId(customer.getBraintreeCustomerId());
        b2bCustomer.setDefaultB2BUnit(registration.getDefaultB2BUnit());
        if (customer.getEncodedPassword() == null) {
            getUserService().setPassword(b2bCustomer, StringUtils.EMPTY, PasswordEncoderConstants.DEFAULT_ENCODING);
        }
        b2bCustomer.setPasswordForSingleAuthenticationActive(customer.isPasswordForSingleAuthenticationActive());

        final List<PaymentInfoModel> paymentInfoModels = new ArrayList<>(customer.getPaymentInfos());
        final List<BrainTreePaymentInfoModel> paymentInfoClones = new ArrayList<>();

        for (PaymentInfoModel paymentInfoModel : paymentInfoModels) {
            if (paymentInfoModel instanceof BrainTreePaymentInfoModel) {
                BrainTreePaymentInfoModel brainTreePaymentInfoModel = (BrainTreePaymentInfoModel) paymentInfoModel;
                if(BrainTreeUtils.isPayPalPayment(brainTreePaymentInfoModel.getPaymentProvider())){
                    BrainTreePaymentInfoModel paymentInfoClone = getModelService()
                        .clone(brainTreePaymentInfoModel);
                    paymentInfoClone.setUser(b2bCustomer);
                    paymentInfoClones.add(paymentInfoClone);
                }
            }
        }
        paymentInfoClones.stream().findFirst().ifPresent(b2bCustomer::setDefaultPaymentInfo);

        final List<AddressModel> addressModels = new ArrayList<>(customer.getAddresses());
        final List<AddressModel> addressClones = new ArrayList<>();

        for (AddressModel addressModel : addressModels) {
            AddressModel addressClone = getModelService().clone(addressModel);
            addressClone.setOwner(b2bCustomer);
            addressClones.add(addressClone);
        }

        addressClones.stream().findFirst().ifPresent(addressClone -> {
            b2bCustomer.setDefaultShipmentAddress(addressClone);
            b2bCustomer.setDefaultPaymentAddress(addressClone);
        });

        final Map<String, Object> params = ImmutableMap.of(InterceptorExecutionPolicy.DISABLED_INTERCEPTOR_BEANS,
                ImmutableSet.of("brainTreeCustomerRemoveInterceptor"));
        sessionService.executeInLocalViewWithParams(params, new SessionExecutionBody()
        {
            @Override
            public void executeWithoutResult()
            {
                getModelService().remove(customer);
            }
        });

        paymentInfoClones.forEach(getModelService()::save);
        addressClones.forEach(getModelService()::save);

        return b2bCustomer;
    }

    public SessionService getSessionService()
    {
        return sessionService;
    }

    public void setSessionService(final SessionService sessionService)
    {
        this.sessionService = sessionService;
    }
}
