package com.braintree.customersupportbackoffice.facade.impl;

import com.braintree.command.request.BrainTreeCloneTransactionRequest;
import com.braintree.command.request.BrainTreeCreateCreditCardPaymentMethodRequest;
import com.braintree.command.request.BrainTreeCustomerRequest;
import com.braintree.command.request.BrainTreeFindTransactionRequest;
import com.braintree.command.request.BrainTreeRefundTransactionRequest;
import com.braintree.command.request.BrainTreeSaleTransactionRequest;
import com.braintree.command.result.BrainTreeAbstractTransactionResult;
import com.braintree.command.result.BrainTreeCloneTransactionResult;
import com.braintree.command.result.BrainTreeCustomerResult;
import com.braintree.command.result.BrainTreeFindCustomersResult;
import com.braintree.command.result.BrainTreeFindTransactionResult;
import com.braintree.command.result.BrainTreePaymentMethodResult;
import com.braintree.command.result.BrainTreeRefundTransactionResult;
import com.braintree.command.result.BrainTreeSaleTransactionResult;
import com.braintree.command.result.BrainTreeVoidResult;
import com.braintree.configuration.service.BrainTreeConfigService;
import com.braintree.customersupportbackoffice.data.BrainTreeTransactionInfo;
import com.braintree.customersupportbackoffice.facade.BrainTreeCustomerSupportFacade;
import com.braintree.customersupportbackoffice.services.BrainTreeCustomerSearchService;
import com.braintree.customersupportbackoffice.services.BrainTreeTransactionSearchService;
import com.braintree.hybris.data.BrainTreeResponseResultData;
import com.braintree.hybris.data.BraintreeTransactionData;
import com.braintree.hybris.data.BraintreeTransactionEntryData;
import com.braintree.method.BrainTreePaymentService;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.model.BrainTreeTransactionDetailModel;
import com.braintree.model.BraintreeCustomerDetailsModel;
import com.braintree.payment.dto.BraintreeInfo;
import com.braintree.payment.info.service.BraintreePaymentInfoService;
import com.braintree.transaction.service.BrainTreeTransactionService;
import com.braintreegateway.Customer;
import com.braintreegateway.PaymentMethod;
import com.hybris.backoffice.widgets.advancedsearch.impl.AdvancedSearchData;
import com.hybris.backoffice.widgets.advancedsearch.impl.SearchConditionData;
import de.hybris.platform.core.enums.OrderStatus;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.core.model.user.UserModel;
import de.hybris.platform.payment.AdapterException;
import de.hybris.platform.payment.commands.request.CreateSubscriptionRequest;
import de.hybris.platform.payment.commands.request.VoidRequest;
import de.hybris.platform.payment.commands.result.SubscriptionResult;
import de.hybris.platform.payment.dto.BillingInfo;
import de.hybris.platform.payment.dto.CardInfo;
import de.hybris.platform.payment.dto.TransactionStatus;
import de.hybris.platform.payment.model.PaymentTransactionModel;
import de.hybris.platform.servicelayer.dto.converter.Converter;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.session.SessionService;
import de.hybris.platform.servicelayer.user.UserService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;
import org.zkoss.zul.Messagebox;

import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage;

public class DefaultBrainTreeCustomerSupportFacade implements BrainTreeCustomerSupportFacade {

    private static final Logger LOG = Logger.getLogger(DefaultBrainTreeCustomerSupportFacade.class);

    private ModelService modelService;
    private UserService userService;
    private BrainTreeCustomerSearchService customerSearchService;
    private BrainTreeTransactionSearchService transactionSearchService;
    private BrainTreePaymentService brainTreePaymentService;
    private BrainTreeTransactionService brainTreeTransactionService;
    private BraintreePaymentInfoService paymentInfoService;
    private BrainTreeConfigService brainTreeConfigService;
    private Converter<BraintreeTransactionEntryData, BrainTreeTransactionDetailModel> transactionDetailPopulator;
    private Converter<BrainTreeAbstractTransactionResult, BrainTreeResponseResultData> brainTreeCustomerSupportResponseConverter;
    private Converter<PaymentMethod, BrainTreePaymentInfoModel> paymentMethodConverter;

    @Override
    public BraintreeCustomerDetailsModel findCustomer(final String customerId) throws AdapterException {
        final UserModel user = userService.getCurrentUser();
        final String braintreeCustomerId = user.getUid();
        if (braintreeCustomerId != null) {
            final BrainTreeCustomerRequest findCustomerRequest = new BrainTreeCustomerRequest(
                braintreeCustomerId);
            findCustomerRequest.setCustomerId(customerId);

            final BrainTreeFindCustomersResult customers = customerSearchService.findCustomers(findCustomerRequest);
            if (customers.getCustomers() != null && !customers.getCustomers().isEmpty()) {
                return customers.getCustomers().get(0);
            }
        }
        LOG.error("[BT Payment Service] Error user must be Customer type!");
        return null;
    }

    @Override
    public List<BraintreeCustomerDetailsModel> findCustomers(AdvancedSearchData searchData) throws AdapterException {
        final UserModel user = userService.getCurrentUser();
        final String braintreeCustomerId = user.getUid();
        if (braintreeCustomerId != null) {
            final BrainTreeCustomerRequest findCustomerRequest = new BrainTreeCustomerRequest(
                braintreeCustomerId);

            List<SearchConditionData> customerId = searchData.getConditions("braintreeTransactionCustomerID");
            if (customerId != null && !customerId.isEmpty()) {
                addCustomerIdCondition(findCustomerRequest, customerId.get(0));
            }

            List<SearchConditionData> customerEmail = searchData.getConditions("braintreeTransactionCustomerEmail");
            if (customerEmail != null && !customerEmail.isEmpty()) {
                addCustomerEmailCondition(findCustomerRequest, customerEmail.get(0));
            }

            final BrainTreeFindCustomersResult customers = customerSearchService.findCustomers(findCustomerRequest);

            int searchLimit = brainTreeConfigService.getBackofficeSearchLimit();
            if (customers.isExceedLimit()) {
                Messagebox.show("Too many search results ()! Limit is " + searchLimit
                        + ". Please enter at least customer id or customer email.",
                    "Customer search", Messagebox.OK, Messagebox.ERROR);

                return Collections.emptyList();
            }

            return customers.getCustomers();
        }
        return Collections.emptyList();
    }

    private void addCustomerIdCondition(final BrainTreeCustomerRequest findCustomerRequest,
        final SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findCustomerRequest.setCustomerId(searchConditionData.getValue().toString());
        }
    }

    private void addCustomerEmailCondition(final BrainTreeCustomerRequest findCustomerRequest,
        final SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findCustomerRequest.setCustomerEmail(searchConditionData.getValue().toString());
            findCustomerRequest.setCustomerEmailOperator(searchConditionData.getOperator().name());
        }
    }

    @Override
    public List<BrainTreeTransactionDetailModel> findTransactions(AdvancedSearchData searchData)
        throws AdapterException {
        final UserModel user = userService.getCurrentUser();
        final String braintreeCustomerId = user.getUid();
        if (braintreeCustomerId != null) {
            final BrainTreeFindTransactionRequest findTransactionRequest = new BrainTreeFindTransactionRequest(
                braintreeCustomerId);

            Optional.ofNullable(searchData.getConditions("braintreeTransactionCustomerID"))
                .orElseGet(Collections::emptyList)
                .stream()
                .findFirst()
                .ifPresent(searchConditionData -> addTransactionCustomerIdCondition(findTransactionRequest,
                    searchConditionData));

            Optional.ofNullable(searchData.getConditions("braintreeTransactionCustomerEmail"))
                .orElseGet(Collections::emptyList)
                .stream()
                .findFirst()
                .ifPresent(searchConditionData -> addTransactionCustomerEmailCondition(findTransactionRequest,
                    searchConditionData));

            Optional.ofNullable(searchData.getConditions("braintreeTransactionDetailID"))
                .orElseGet(Collections::emptyList)
                .stream()
                .findFirst()
                .ifPresent(
                    searchConditionData -> addTransactionIdCondition(findTransactionRequest, searchConditionData));

            Optional.ofNullable(searchData.getConditions("braintreeTransactionDetailStatus"))
                .orElseGet(Collections::emptyList)
                .stream()
                .findFirst()
                .ifPresent(
                    searchConditionData -> addTransactionStatusCondition(findTransactionRequest, searchConditionData));

            Optional.ofNullable(searchData.getConditions("braintreeTransactionDetailRiskDecision"))
                .orElseGet(Collections::emptyList)
                .stream()
                .findFirst()
                .ifPresent(searchConditionData -> addTransactionRiskDecisionCondition(findTransactionRequest,
                    searchConditionData));

            SearchConditionData dateFrom = Optional
                .ofNullable(searchData.getConditions("braintreeTransactionDetailDateFrom"))
                .orElseGet(Collections::emptyList).stream()
                .findFirst()
                .orElse(null);

            SearchConditionData dateTo = Optional
                .ofNullable(searchData.getConditions("braintreeTransactionDetailDateTo"))
                .orElseGet(Collections::emptyList).stream()
                .findFirst().
                    orElse(null);

            try {
                addTransactionDateRange(findTransactionRequest, dateFrom, dateTo);
            } catch (IllegalArgumentException e) {
                Messagebox.show(e.getMessage(), "Transaction search", Messagebox.OK, Messagebox.ERROR);
                return Collections.emptyList();
            }

            final BrainTreeFindTransactionResult transactions = transactionSearchService
                .findTransactions(findTransactionRequest);

            int searchLimit = brainTreeConfigService.getBackofficeSearchLimit();
            if (transactions.isExceedLimit()) {
                Messagebox.show("Too many results! Limit is " + searchLimit +
                        " Please type transaction id or customer email.",
                    "Transaction search", Messagebox.OK, Messagebox.ERROR);

                return Collections.emptyList();
            }

            final List<BrainTreeTransactionDetailModel> transactionList = new ArrayList<>(
                transactions.getTransactionData().getTransactionEntries().size());
            BraintreeTransactionData transactionData = transactions.getTransactionData();
            transactionData.getTransactionEntries()
                .forEach(transactionEntry -> transactionList.add(transactionDetailPopulator.convert(transactionEntry)));

            return filterTransactionsAfter(transactionList, searchData);
        }
        return Collections.emptyList();
    }

    private List<BrainTreeTransactionDetailModel> filterTransactionsAfter(
        List<BrainTreeTransactionDetailModel> transactionList, AdvancedSearchData searchData) {
        List<BrainTreeTransactionDetailModel> result = new ArrayList<>();
        for (BrainTreeTransactionDetailModel brainTreeTransactionDetailModel : transactionList) {
            boolean addToResults = true;
            List<SearchConditionData> transactionRiskDecision = searchData
                .getConditions("braintreeTransactionDetailRiskDecision");
            if (transactionRiskDecision != null && !transactionRiskDecision.isEmpty()) {
                SearchConditionData searchConditionData = transactionRiskDecision.get(0);
                if (searchConditionData != null && searchConditionData.getValue() != null
                    && !StringUtils.equalsIgnoreCase(searchConditionData.getValue().toString(),
                    brainTreeTransactionDetailModel.getRiskDecision())) {
                    addToResults = false;
                }
            }

            if (addToResults) {
                result.add(brainTreeTransactionDetailModel);
            }
        }
        return result;
    }

    @Override
    public BraintreeTransactionEntryData findTransaction(String transactionId) {
        final String merchantTransactionCode = getMerchantCode();
        if (merchantTransactionCode != null) {
            final BrainTreeFindTransactionRequest findTransactionRequest = new BrainTreeFindTransactionRequest(
                merchantTransactionCode);

            findTransactionRequest.setTransactionId(transactionId);

            final BrainTreeFindTransactionResult transactions = transactionSearchService
                .findTransactions(findTransactionRequest);

            final BraintreeTransactionData convert = transactions.getTransactionData();

            List<BraintreeTransactionEntryData> brainTreeTransactions = convert.getTransactionEntries();

            if (CollectionUtils.isNotEmpty(brainTreeTransactions)) {
                return convert.getTransactionEntries().get(0);
            }
        }

        return null;
    }

    private void addTransactionCustomerIdCondition(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findTransactionRequest.setCustomerId(searchConditionData.getValue().toString());
        }
    }

    private void addTransactionCustomerEmailCondition(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findTransactionRequest.setCustomerEmail(searchConditionData.getValue().toString());
            findTransactionRequest.setCustomerEmailOperator(searchConditionData.getOperator().name());
        }
    }

    private void addTransactionIdCondition(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findTransactionRequest.setTransactionId(searchConditionData.getValue().toString());
        }
    }

    private void addTransactionStatusCondition(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findTransactionRequest.setTransactionStatus(searchConditionData.getValue().toString());
        }
    }

    private void addTransactionRiskDecisionCondition(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData searchConditionData) {
        if (searchConditionData != null && searchConditionData.getValue() != null) {
            findTransactionRequest.setRiskDecision(searchConditionData.getValue().toString());
        }
    }

    private void addTransactionDateRange(BrainTreeFindTransactionRequest findTransactionRequest,
        SearchConditionData dateFrom, SearchConditionData dateTo) {
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        start.add(Calendar.DAY_OF_MONTH, -1);

        if (dateFrom != null && dateFrom.getValue() != null) {
            start.setTime((Date) dateFrom.getValue());
        }
        if (dateTo != null && dateTo.getValue() != null) {
            end.setTime((Date) dateTo.getValue());
        }

        validateDateRange(start, end);

        findTransactionRequest.setStartDate(start);
        findTransactionRequest.setEndDate(end);
    }

    private static void validateDateRange(Calendar start, Calendar end) {
        if (start.after(end)) {
            throw new IllegalArgumentException("From date should less than To date.");
        }
    }

    @Override
    public BrainTreeResponseResultData refundTransaction(final BrainTreeTransactionDetailModel currentTransaction,
        final String amount) {
        validateParameterNotNullStandardMessage("currentTransaction", currentTransaction);
        final String merchantTransactionCode = getMerchantCode();
        if (merchantTransactionCode != null) {
            final BrainTreeRefundTransactionRequest request = new BrainTreeRefundTransactionRequest(
                merchantTransactionCode);
            request.setTransactionId(currentTransaction.getId());
            if (StringUtils.isNotBlank(amount)) {
                request.setAmount(formedAmount(amount));
            }
            final BrainTreeRefundTransactionResult result = brainTreePaymentService.refundTransaction(request);
            if (TransactionStatus.ACCEPTED.equals(result.getTransactionStatus())) {
                createRefundTransaction(currentTransaction, result);
            }
            return brainTreeCustomerSupportResponseConverter.convert(result);
        }
        return new BrainTreeResponseResultData();
    }

    private String getMerchantCode() {
        final UserModel user = userService.getCurrentUser();
        return user.getUid();
    }

    private static BigDecimal formedAmount(final String amount) {
        return new BigDecimal(amount);
    }

    private void createRefundTransaction(final BrainTreeTransactionDetailModel currentTransaction,
        final BrainTreeRefundTransactionResult result) {
        final OrderModel linkedOrder = currentTransaction.getLinkedOrder();
        if (linkedOrder != null) {
            final List<PaymentTransactionModel> paymentTransactions = linkedOrder.getPaymentTransactions();
            if (CollectionUtils.isNotEmpty(paymentTransactions)) {
                final PaymentTransactionModel transaction = paymentTransactions.iterator().next();
                getBrainTreeTransactionService().createRefundTransaction(transaction, result);
            }
        }
    }

    @Override
    public BrainTreeResponseResultData voidTransaction(final BrainTreeTransactionDetailModel transaction) {
        validateParameterNotNullStandardMessage("transaction", transaction);
        final String merchantTransactionCode = getMerchantCode();
        if (merchantTransactionCode != null) {
            final VoidRequest voidRequest = new VoidRequest(merchantTransactionCode, transaction.getId(),
                StringUtils.EMPTY,
                StringUtils.EMPTY);
            final BrainTreeVoidResult voidResult = brainTreePaymentService.voidTransaction(voidRequest);
            if (TransactionStatus.ACCEPTED.equals(voidResult.getTransactionStatus())) {
                forceOrderCancellation(transaction, voidResult);
            }
            return brainTreeCustomerSupportResponseConverter.convert(voidResult);
        }
        return new BrainTreeResponseResultData();
    }

    private void forceOrderCancellation(final BrainTreeTransactionDetailModel transaction,
        final BrainTreeVoidResult voidResult) {
        final OrderModel linkedOrder = transaction.getLinkedOrder();
        if (linkedOrder != null) {
            final List<PaymentTransactionModel> paymentTransactions = linkedOrder.getPaymentTransactions();
            if (CollectionUtils.isNotEmpty(paymentTransactions)) {
                final PaymentTransactionModel txn = paymentTransactions.iterator().next();
                getBrainTreeTransactionService().createCancelTransaction(txn, voidResult);
            }
            linkedOrder.setStatus(OrderStatus.CANCELLED);
            modelService.save(linkedOrder);
        }
    }

    @Override
    public BrainTreeResponseResultData cloneTransaction(BrainTreeTransactionDetailModel currentTransaction,
        String amount, boolean submitForSettlement) {
        validateParameterNotNullStandardMessage("currentTransaction", currentTransaction);
        final String merchantTransactionCode = getMerchantCode();
        if (merchantTransactionCode != null) {
            final BrainTreeCloneTransactionRequest request = new BrainTreeCloneTransactionRequest(
                merchantTransactionCode);
            request.setTransactionId(currentTransaction.getId());
            if (StringUtils.isNotBlank(amount)) {
                request.setAmount(formedAmount(amount));
            }
            request.setSubmitForSettlement(Boolean.valueOf(submitForSettlement));
            final BrainTreeCloneTransactionResult result = brainTreePaymentService.cloneTransaction(request);
            return brainTreeCustomerSupportResponseConverter.convert(result);
        }
        return new BrainTreeResponseResultData();
    }

    @Override
    public BrainTreePaymentMethodResult createCreditCardPaymentMethod(final String customerId,
        final String paymentMethodNonce,
        final String cardholderName, final boolean isDefault, String billingAddressId) {
        final UserModel user = userService.getCurrentUser();
        final String braintreeCustomerId = user.getUid();
        if (braintreeCustomerId != null) {
            final BrainTreeCreateCreditCardPaymentMethodRequest request = new BrainTreeCreateCreditCardPaymentMethodRequest(
                braintreeCustomerId);
            request.setMethodNonce(paymentMethodNonce);
            request.setCustomerId(customerId);
            request.setCardholderName(cardholderName);
            request.setIsDefault(isDefault);

            if (StringUtils.isNotBlank(billingAddressId)) {
                request.setBillingAddressId(billingAddressId);
            }

            final BrainTreePaymentMethodResult result = brainTreePaymentService.createCreditCardPaymentMethod(request);
            if (result.isSuccess() && result.getPaymentMethod() != null) {
                final BrainTreePaymentInfoModel paymentInfo;

                paymentInfo = paymentMethodConverter.convert(result.getPaymentMethod());

                if (paymentInfo != null) {
                    paymentInfo.setCardholderName(result.getCardholderName());
                    paymentInfoService.addToCustomer(paymentInfo);
                }
            }
            return result;
        }
        return null;
    }

    @Override
    public BrainTreeResponseResultData removeCustomer(final String customerId) {
        final String merchantId = getMerchantCode();
        BrainTreeResponseResultData resultData = new BrainTreeResponseResultData();
        if (merchantId != null) {
            validateParameterNotNullStandardMessage("customerId", customerId);
            final BrainTreeCustomerRequest brainTreeCustomerRequest = new BrainTreeCustomerRequest(merchantId);
            brainTreeCustomerRequest.setCustomerId(customerId);

            final BrainTreeCustomerResult result = brainTreePaymentService.removeCustomer(brainTreeCustomerRequest);

            resultData.setSuccess(result.isSuccess());
            resultData.setErrorMessage(result.getErrorMessage());
            resultData.setErrorCode(result.getErrorCode());
        }
        return resultData;
    }

    @Override
    public BrainTreeResponseResultData createTransaction(BrainTreeTransactionInfo brainTreeInfo) {
        validateParameterNotNullStandardMessage("brainTreeInfo", brainTreeInfo);
        final BrainTreeResponseResultData brainTreeResponseResultData = new BrainTreeResponseResultData();
        return getBraintreeResponseResultData(brainTreeInfo, brainTreeResponseResultData);
    }

    private BrainTreeResponseResultData getBraintreeResponseResultData(final BrainTreeTransactionInfo brainTreeInfo,
        final BrainTreeResponseResultData brainTreeResponseResultData) {
        final String merchantTransactionCode = getMerchantCode();
        if (merchantTransactionCode != null) {
            final BrainTreeSaleTransactionRequest request = new BrainTreeSaleTransactionRequest(merchantTransactionCode,
                createCard(brainTreeInfo), brainTreeInfo.getCurrency(), brainTreeInfo.getAmount(),
                createShippingInfo(brainTreeInfo));

            request.setUsePaymentMethodToken(brainTreeInfo.isPaymentMethodToken());
            request.setPaymentMethodToken(brainTreeInfo.getPaymentMethodToken());
            request.setTaxAmount(brainTreeInfo.getTax());
            request.setCustomFields(brainTreeInfo.getCustom());
            request.setCustomerEmail(brainTreeInfo.getEmail());
            request.setCustomerFirstName(brainTreeInfo.getFirstName());
            request.setCustomerLastName(brainTreeInfo.getLastName());
            request.setMethodNonce(brainTreeInfo.getNonce());
            request.setCardholderName(brainTreeInfo.getCardHolder());

            request.setMerchantAccountIdForCurrentSite(brainTreeInfo.getMerchantAccountId());
            final BrainTreeSaleTransactionResult result = brainTreePaymentService.saleTransaction(request);
            return brainTreeCustomerSupportResponseConverter.convert(result);
        }
        return brainTreeResponseResultData;
    }

    private CardInfo createCard(final BrainTreeTransactionInfo transactionInfo) {
        final CardInfo cardInfo = new CardInfo();
        cardInfo.setCardHolderFullName(transactionInfo.getCardHolder());
        cardInfo.setCardNumber(transactionInfo.getCardNumber());
        cardInfo.setCv2Number(transactionInfo.getCvv());
        if (transactionInfo.getExpirationDate() != null) {
            final String[] mmyy = transactionInfo.getExpirationDate().split("/");
            if (mmyy.length == 2) {
                cardInfo.setExpirationMonth(Integer.valueOf(mmyy[0]));
                cardInfo.setExpirationYear(Integer.valueOf(mmyy[1]));
            }
        }
        final BillingInfo billingInfo = new BillingInfo();
        billingInfo.setFirstName(transactionInfo.getFirstName());
        billingInfo.setLastName(transactionInfo.getLastName());
        billingInfo.setEmail(transactionInfo.getEmail());
        billingInfo.setPostalCode(transactionInfo.getBillingPostCode());
        billingInfo.setStreet1(transactionInfo.getBillingAddress());
        cardInfo.setBillingInfo(billingInfo);
        return cardInfo;
    }

    private BillingInfo createShippingInfo(final BrainTreeTransactionInfo transactionInfo) {
        final BillingInfo shippingInfo = new BillingInfo();
        shippingInfo.setFirstName(transactionInfo.getFirstName());
        shippingInfo.setLastName(transactionInfo.getLastName());
        shippingInfo.setEmail(transactionInfo.getEmail());
        shippingInfo.setPostalCode(transactionInfo.getShippingPostCode());
        shippingInfo.setStreet1(transactionInfo.getShippingAddress());
        return shippingInfo;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void setCustomerSearchService(BrainTreeCustomerSearchService customerSearchService) {
        this.customerSearchService = customerSearchService;
    }

    public void setTransactionSearchService(BrainTreeTransactionSearchService transactionSearchService) {
        this.transactionSearchService = transactionSearchService;
    }

    public void setTransactionDetailPopulator(
        Converter<BraintreeTransactionEntryData, BrainTreeTransactionDetailModel> transactionDetailPopulator) {
        this.transactionDetailPopulator = transactionDetailPopulator;
    }

    public void setBrainTreePaymentService(BrainTreePaymentService brainTreePaymentService) {
        this.brainTreePaymentService = brainTreePaymentService;
    }

    public BrainTreeTransactionService getBrainTreeTransactionService() {
        return brainTreeTransactionService;
    }

    public void setBrainTreeTransactionService(BrainTreeTransactionService brainTreeTransactionService) {
        this.brainTreeTransactionService = brainTreeTransactionService;
    }

    public void setBrainTreeCustomerSupportResponseConverter(
        Converter<BrainTreeAbstractTransactionResult, BrainTreeResponseResultData> brainTreeCustomerSupportResponseConverter) {
        this.brainTreeCustomerSupportResponseConverter = brainTreeCustomerSupportResponseConverter;
    }

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

    public void setPaymentMethodConverter(Converter<PaymentMethod, BrainTreePaymentInfoModel> paymentMethodConverter) {
        this.paymentMethodConverter = paymentMethodConverter;
    }

    public void setPaymentInfoService(BraintreePaymentInfoService paymentInfoService) {
        this.paymentInfoService = paymentInfoService;
    }

    public void setBrainTreeConfigService(BrainTreeConfigService brainTreeConfigService) {
        this.brainTreeConfigService = brainTreeConfigService;
    }
}
