package com.braintree.transaction.service;

import com.braintree.command.result.BrainTreeAbstractTransactionResult;
import com.braintree.command.result.BrainTreeRefundTransactionResult;
import com.braintree.command.result.BrainTreeVoidResult;
import com.braintree.enums.BraintreePaymentTransactionStatus;
import com.braintree.hybris.data.BrainTreeSubscriptionInfoData;
import com.braintree.hybris.data.BraintreeTransactionEntryData;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.model.PaymentTransactionLogEntryModel;
import de.hybris.platform.commerceservices.service.data.CommerceOrderParameter;
import de.hybris.platform.core.enums.OrderStatus;
import de.hybris.platform.core.model.order.AbstractOrderModel;
import de.hybris.platform.core.model.order.CartModel;
import de.hybris.platform.core.model.user.AddressModel;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.core.servicelayer.data.SearchPageData;
import de.hybris.platform.payment.enums.PaymentTransactionType;
import de.hybris.platform.payment.model.PaymentTransactionEntryModel;
import de.hybris.platform.payment.model.PaymentTransactionModel;

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

public interface BrainTreeTransactionService {

    void createPaymentMethodTokenForOrderReplenishment();

    PaymentTransactionEntryModel createCancelTransaction(PaymentTransactionModel transaction,
        BrainTreeVoidResult voidResult);

    PaymentTransactionEntryModel createRefundTransaction(PaymentTransactionModel transaction,
        BrainTreeRefundTransactionResult result);

    PaymentTransactionEntryModel createPartialRefundTransaction(PaymentTransactionEntryModel transactionEntry,
        BrainTreeRefundTransactionResult result, final BigDecimal amount);

    PaymentTransactionEntryModel createPaymentTransaction(final PaymentTransactionModel transaction,
        final BrainTreeAbstractTransactionResult result, final BigDecimal amount,
        final PaymentTransactionType transactionType, final String authorizeTransactionID);

    PaymentTransactionEntryModel createPaymentTransaction(PaymentTransactionModel transaction,
        BrainTreeAbstractTransactionResult result, BigDecimal amount, PaymentTransactionType transactionType);

    PaymentTransactionEntryModel createAuthorizationTransaction(final CommerceOrderParameter parameter);

    PaymentTransactionEntryModel createAuthorizationTransactionForCapture(final CommerceOrderParameter parameter, boolean isOrderToBeForceCompleted);

    PaymentTransactionLogEntryModel createTransactionLogEntry(String interactionType, String status,
        String paymentInstrumentType, String achReturnCode, Date date);

    BrainTreePaymentInfoModel createPaymentMethodInfo(final AddressModel billingAddress,
        final CustomerModel customerModel, final BrainTreeSubscriptionInfoData braintreeInfo);

    PaymentTransactionEntryModel createTransactionEntryForLocalPaymentReversed(final CartModel cart,
        final PaymentTransactionType paymentTransactionType);

    void createPaymentTransactionForLocalPaymentReversed(final AbstractOrderModel cart,
        List<PaymentTransactionEntryModel> paymentTransactionEntrys);

    /**
     * Used to add transaction log
     * @param transaction
     * @param result
     * @param interactionType
     */
    void addTransactionLog(final PaymentTransactionModel transaction, BrainTreeAbstractTransactionResult result,
        String interactionType);

    /**
     * Used to get graphQL id from transaction
     * @param legacyId
     * @return String
     */
    String getGraphQLIdFromTransaction(final String legacyId);

    /**
     * This method is used to calculate total amount
     *
     * @param cart order model
     * @return total amount
     */
    BigDecimal calculateTotalAmount(final AbstractOrderModel cart);

    void saveBraintreeTransactionStatus(String status, PaymentTransactionModel paymentTransactionModel);

    SearchPageData<PaymentTransactionModel> getPaymentTransactionsByStatuses(
            List<BraintreePaymentTransactionStatus> statuses, SearchPageData<PaymentTransactionModel> searchPage);

    void updateBraintreePaymentTransactionStatuses(List<PaymentTransactionModel> transactionModels);

    boolean isCustomerHaveNotCapturedOrdersForPaymentDetails(CustomerModel currentCustomer, BrainTreePaymentInfoModel brainTreePaymentInfo);

    void saveVoidTransactionEntry(PaymentTransactionEntryModel entry, OrderStatus status);

    PaymentTransactionEntryModel createTransactionEntry(BraintreeTransactionEntryData entryData,
                                                        PaymentTransactionModel transactionModel,
                                                        PaymentTransactionType type);

    PaymentTransactionLogEntryModel createTransactionLogEntry(BrainTreeAbstractTransactionResult result,
                                                              String interactionType);

    void saveRejectedTransactionEntry(PaymentTransactionEntryModel entry, OrderStatus status);

    void saveTransactionLogEntry(PaymentTransactionEntryModel entryModel);

    void saveTransactionLogEntry(PaymentTransactionEntryModel entryModel, BraintreeTransactionEntryData entryData);

    PaymentTransactionModel findTransactionByTransactionId(String transactionId);

}
