package com.braintree.actions.order;

import com.braintree.BrainTreeCheckOrderService;
import de.hybris.platform.core.enums.OrderStatus;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.orderprocessing.model.OrderProcessModel;
import de.hybris.platform.payment.enums.PaymentTransactionType;
import de.hybris.platform.processengine.action.AbstractSimpleDecisionAction;
import org.apache.log4j.Logger;

import static com.braintree.constants.BraintreeConstants.FAKE_REQUEST_ID;


/**
 * This example action checks the order for required data in the business process. Skipping this action may result in
 * failure in one of the subsequent steps of the process. The relation between the order and the business process is
 * defined in basecommerce extension through item OrderProcess. Therefore if your business process has to access the
 * order (a typical case), it is recommended to use the OrderProcess as a parentClass instead of the plain
 * BusinessProcess.
 */
public class BrainTreeCheckOrderAction extends AbstractSimpleDecisionAction<OrderProcessModel> {

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

    private BrainTreeCheckOrderService checkOrderService;

    @Override
    public Transition executeAction(final OrderProcessModel process) {
        final OrderModel order = process.getOrder();

        if (order == null) {
            LOG.error("Missing the order, exiting the process");
            return Transition.NOK;
        }
        if (isLocalPaymentReversedOrder(order)) {
            setOrderStatus(order, OrderStatus.PAYMENT_REVERSED);
            return Transition.NOK;
        }

        if (checkOrderService.check(order)) {
            setOrderStatus(order, OrderStatus.CHECKED_VALID);
            return Transition.OK;
        } else {
            setOrderStatus(order, OrderStatus.CHECKED_INVALID);
            return Transition.NOK;
        }
    }

    protected boolean isLocalPaymentReversedOrder(OrderModel order) {
        return order.getPaymentTransactions().stream().flatMap(transactionModel -> transactionModel.getEntries().stream())
                .anyMatch(transaction -> (PaymentTransactionType.REFUND_FOLLOW_ON.equals(transaction.getType())
                        && FAKE_REQUEST_ID.equalsIgnoreCase(transaction.getRequestId())));
    }

    public void setCheckOrderService(final BrainTreeCheckOrderService checkOrderService) {
        this.checkOrderService = checkOrderService;
    }

}
