package com.braintree.facade.backoffice.impl;

import com.braintree.command.result.BrainTreeAdjustedAuthorizationResult;
import com.braintree.enums.BraintreePaymentTransactionStatus;
import com.braintree.exceptions.BraintreeErrorException;
import com.braintree.facade.backoffice.BraintreeBackofficeAdjustAuthorizationFacade;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.order.adjust.authorization.BraintreeAdjustAuthorizationService;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.payment.enums.PaymentTransactionType;
import de.hybris.platform.payment.model.PaymentTransactionEntryModel;
import de.hybris.platform.payment.model.PaymentTransactionModel;
import de.hybris.platform.servicelayer.model.ModelService;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class DefaultBraintreeBackofficeAdjustAuthorizationFacade implements BraintreeBackofficeAdjustAuthorizationFacade {

    private static final Logger LOG = Logger.getLogger(DefaultBraintreeBackofficeAdjustAuthorizationFacade.class);
    private static final String ORDER_MODEL_IS_NULL = "OrderModel is null";

    private ModelService modelService;
    private BraintreeAdjustAuthorizationService braintreeAdjustAuthorizationService;

    @Override
    public boolean isAdjustAuthorizationPossible(final OrderModel order) {
        if (null == order) {
            LOG.warn(ORDER_MODEL_IS_NULL);
            return false;
        }

        boolean isAdjustAuthorizationPossible = false;

        modelService.refresh(order);

        if (order.getPaymentInfo() instanceof BrainTreePaymentInfoModel) {
            for (PaymentTransactionModel transaction : order.getPaymentTransactions()) {
                isAdjustAuthorizationPossible = braintreeAdjustAuthorizationService.isAdjustAuthorizationPossible(order, transaction);
            }
        }

        return isAdjustAuthorizationPossible;
    }

    @Override
    public BrainTreeAdjustedAuthorizationResult adjustAuthorization(OrderModel orderModel, String transactionId,
                                                                    BigDecimal amount) throws BraintreeErrorException {
        return braintreeAdjustAuthorizationService.adjustAuthorization(orderModel, transactionId, amount);
    }

    @Override
    public List<PaymentTransactionEntryModel> getAuthorizedTransactions(final OrderModel order) {
        List<PaymentTransactionEntryModel> result = new ArrayList<>();

        for (PaymentTransactionModel transaction : order.getPaymentTransactions()) {
            if (transaction.getBraintreePaymentTransactionStatus()
                    .equals(BraintreePaymentTransactionStatus.AUTHORIZED)) {
                transaction.getEntries()
                        .stream()
                        .filter(paymentEntry -> PaymentTransactionType.AUTHORIZATION.equals(paymentEntry.getType()))
                        .findFirst()
                        .ifPresent(result::add);
            }
        }

        return result;
    }

    @Override
    public BigDecimal getAmountByTransactionId(final OrderModel orderModel, final String transactionId) {
        PaymentTransactionEntryModel transaction =
                braintreeAdjustAuthorizationService.getTransactionEntryById(orderModel, transactionId);
        return transaction.getAmount();
    }

    @Override
    public BigDecimal getOriginalAmountByTransactionId(final OrderModel orderModel, final String transactionId) {
        PaymentTransactionEntryModel transaction =
                braintreeAdjustAuthorizationService.getTransactionEntryById(orderModel, transactionId);
        return transaction.getOriginalAmount();
    }

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

    public void setBraintreeAdjustAuthorizationService(BraintreeAdjustAuthorizationService braintreeAdjustAuthorizationService) {
        this.braintreeAdjustAuthorizationService = braintreeAdjustAuthorizationService;
    }

}
