/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */

package org.apache.ofbiz.accounting.finaccount;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.ofbiz.accounting.payment.PaymentGatewayServices;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.order.finaccount.FinAccountHelper;
import org.apache.ofbiz.order.order.OrderReadHelper;
import org.apache.ofbiz.product.store.ProductStoreWorker;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceUtil;

/**
 * FinAccountPaymentServices - Financial account used as payment method
 */
public class FinAccountPaymentServices {

    public static final String module = FinAccountPaymentServices.class.getName();
    public static final String resourceError = "AccountingErrorUiLabels";

    // base payment integration services
    public static Map<String, Object> finAccountPreAuth(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        String finAccountCode = (String) context.get("finAccountCode");
        String finAccountPin = (String) context.get("finAccountPin");
        String finAccountId = (String) context.get("finAccountId");
        String orderId = (String) context.get("orderId");
        BigDecimal amount = (BigDecimal) context.get("processAmount");

        // check for an existing auth trans and cancel it
        GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref);
        if (authTrans != null) {
            Map<String, Object> input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTrans.get("referenceNum"));
            try {
                dispatcher.runSync("expireFinAccountAuth", input);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }
        if (finAccountId == null && paymentPref != null) {
            finAccountId = paymentPref.getString("finAccountId");
        }

        // obtain the order information
        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);

        // NOTE DEJ20070808: this means that we want store related settings for where the item is being purchased,
        //NOT where the account was setup; should this be changed to use settings from the store where the account was setup?
        String productStoreId = orh.getProductStoreId();

        // TODO, NOTE DEJ20070808: why is this setup this way anyway? for the allowAuthToNegative wouldn't that be better setup
        //on the FinAccount and not on the ProductStoreFinActSetting? maybe an override on the FinAccount would be good...

        // get the financial account
        GenericValue finAccount;
        if (finAccountId != null) {
            try {
                finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        } else {
            if (finAccountCode != null) {
                try {
                    finAccount = FinAccountHelper.getFinAccountFromCode(finAccountCode, delegator);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "AccountingFinAccountCannotLocateItFromAccountCode", locale));
                }
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingFinAccountIdAndFinAccountCodeAreNull", locale));
            }
        }
        if (finAccount == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountIdInvalid", locale));
        }

        String finAccountTypeId = finAccount.getString("finAccountTypeId");
        finAccountId = finAccount.getString("finAccountId");
        String statusId = finAccount.getString("statusId");

        try {
            // fin the store requires a pin number; validate the PIN with the code
            Map<String, Object> findProductStoreFinActSettingMap = UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "finAccountTypeId", finAccountTypeId);
            GenericValue finAccountSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting").where(findProductStoreFinActSettingMap).cache().queryOne();

            if (finAccountSettings == null) {
                Debug.logWarning("In finAccountPreAuth could not find ProductStoreFinActSetting record, values searched by: " + findProductStoreFinActSettingMap, module);
            }
            if (Debug.verboseOn()) Debug.logVerbose("In finAccountPreAuth finAccountSettings=" + finAccountSettings, module);

            BigDecimal minBalance = FinAccountHelper.ZERO;
            String allowAuthToNegative = "N";

            if (finAccountSettings != null) {
                allowAuthToNegative = finAccountSettings.getString("allowAuthToNegative");
                minBalance = finAccountSettings.getBigDecimal("minBalance");
                if (minBalance == null) {
                    minBalance = FinAccountHelper.ZERO;
                }

                // validate the PIN if the store requires it
                if ("Y".equals(finAccountSettings.getString("requirePinCode"))) {
                    if (!FinAccountHelper.validatePin(delegator, finAccountCode, finAccountPin)) {
                        Map<String, Object> result = ServiceUtil.returnSuccess();
                        result.put("authMessage", UtilProperties.getMessage(resourceError, 
                                "AccountingFinAccountPinCodeCombinatorNotFound", locale));
                        result.put("authResult", Boolean.FALSE);
                        result.put("processAmount", amount);
                        result.put("authFlag", "0");
                        result.put("authCode", "A");
                        result.put("authRefNum", "0");
                        Debug.logWarning("Unable to auth FinAccount: " + result, module);
                        return result;
                    }
                }
            }

            // check for expiration date
            if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
                Map<String, Object> result = ServiceUtil.returnSuccess();
                result.put("authMessage", UtilProperties.getMessage(resourceError, 
                        "AccountingFinAccountExpired", 
                        UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
                result.put("authResult", Boolean.FALSE);
                result.put("processAmount", amount);
                result.put("authFlag", "0");
                result.put("authCode", "A");
                result.put("authRefNum", "0");
                Debug.logWarning("Unable to auth FinAccount: " + result, module);
                return result;
            }

            // check for account being in bad standing somehow
            if ("FNACT_NEGPENDREPL".equals(statusId) || "FNACT_MANFROZEN".equals(statusId) || "FNACT_CANCELLED".equals(statusId)) {
                // refresh the finaccount
                finAccount.refresh();
                statusId = finAccount.getString("statusId");

                if ("FNACT_NEGPENDREPL".equals(statusId) || "FNACT_MANFROZEN".equals(statusId) || "FNACT_CANCELLED".equals(statusId)) {
                    Map<String, Object> result = ServiceUtil.returnSuccess();
                    if ("FNACT_NEGPENDREPL".equals(statusId)) {
                        result.put("authMessage", UtilProperties.getMessage(resourceError, 
                                "AccountingFinAccountNegative", locale));
                    } else if ("FNACT_MANFROZEN".equals(statusId)) {
                        result.put("authMessage", UtilProperties.getMessage(resourceError, 
                                "AccountingFinAccountFrozen", locale));
                    } else if ("FNACT_CANCELLED".equals(statusId)) {
                        result.put("authMessage", UtilProperties.getMessage(resourceError, 
                                "AccountingFinAccountCancelled", locale));
                    }
                    result.put("authResult", Boolean.FALSE);
                    result.put("processAmount", amount);
                    result.put("authFlag", "0");
                    result.put("authCode", "A");
                    result.put("authRefNum", "0");
                    Debug.logWarning("Unable to auth FinAccount: " + result, module);
                    return result;
                }
            }

            // check the amount to authorize against the available balance of fin account, which includes active authorizations as well as transactions
            BigDecimal availableBalance = finAccount.getBigDecimal("availableBalance");
            if (availableBalance == null) {
                availableBalance = FinAccountHelper.ZERO;
            } else {
                BigDecimal availableBalanceOriginal = availableBalance;
                availableBalance = availableBalance.setScale(FinAccountHelper.decimals, FinAccountHelper.rounding);
                if (availableBalance.compareTo(availableBalanceOriginal) != 0) {
                    Debug.logWarning("In finAccountPreAuth for finAccountId [" + finAccountId + "] availableBalance [" + availableBalanceOriginal + "] was different after rounding [" + availableBalance + "]; it should never have made it into the database this way, so check whatever put it there.", module);
                }
            }


            Map<String, Object> result = ServiceUtil.returnSuccess();
            String authMessage = null;
            Boolean processResult;
            String refNum;

            // make sure to round and scale it to the same as availableBalance
            amount = amount.setScale(FinAccountHelper.decimals, FinAccountHelper.rounding);

            Debug.logInfo("Allow auth to negative: " + allowAuthToNegative + " :: available: " + availableBalance + " comp: " + minBalance + " = " + availableBalance.compareTo(minBalance) + " :: req: " + amount, module);
            // check the available balance to see if we can auth this tx
            if (("Y".equals(allowAuthToNegative) && availableBalance.compareTo(minBalance) > -1)
                    || (availableBalance.compareTo(amount) > -1)) {
                Timestamp thruDate;

                if (finAccountSettings != null && finAccountSettings.getLong("authValidDays") != null) {
                    thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), finAccountSettings.getLong("authValidDays"));
                } else {
                    thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), Long.valueOf(30)); // default 30 days for an auth
                }

                Map<String, Object> tmpResult = dispatcher.runSync("createFinAccountAuth", UtilMisc.<String, Object>toMap("finAccountId", finAccountId,
                        "amount", amount, "thruDate", thruDate, "userLogin", userLogin));

                if (ServiceUtil.isError(tmpResult)) {
                    return tmpResult;
                }
                refNum = (String) tmpResult.get("finAccountAuthId");
                processResult = Boolean.TRUE;

                // refresh the account
                finAccount.refresh();
            } else {
                Debug.logWarning("Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "] for finAccountId [" + finAccountId + "]", module);
                refNum = "0"; // a refNum is always required from authorization
                authMessage = "Insufficient funds";
                processResult = Boolean.FALSE;
            }

            result.put("processAmount", amount);
            result.put("authMessage", authMessage);
            result.put("authResult", processResult);
            result.put("processAmount", amount);
            result.put("authFlag", "1");
            result.put("authCode", "A");
            result.put("authRefNum", refNum);
            Debug.logInfo("FinAccont Auth: " + result, module);

            return result;
        } catch (GenericEntityException ex) {
            Debug.logError(ex, "Cannot authorize financial account", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountCannotBeAuthorized", 
                    UtilMisc.toMap("errorString", ex.getMessage()), locale));
        } catch (GenericServiceException ex) {
            Debug.logError(ex, "Cannot authorize financial account", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountCannotBeAuthorized", 
                    UtilMisc.toMap("errorString", ex.getMessage()), locale));
        }
    }

    public static Map<String, Object> finAccountReleaseAuth(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        Locale locale = (Locale) context.get("locale");

        String err = UtilProperties.getMessage(resourceError, "AccountingFinAccountCannotBeExpired", locale);
        try {

            // expire the related financial authorization transaction
            GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
            if (authTransaction == null) {
                return ServiceUtil.returnError(err + UtilProperties.getMessage(resourceError, 
                        "AccountingFinAccountCannotFindAuthorization", locale));
            }

            Map<String, Object> input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTransaction.get("referenceNum"));
            Map<String, Object> serviceResults = dispatcher.runSync("expireFinAccountAuth", input);

            Map<String, Object> result = ServiceUtil.returnSuccess();
            result.put("releaseRefNum", authTransaction.getString("referenceNum"));
            result.put("releaseAmount", authTransaction.getBigDecimal("amount"));
            result.put("releaseResult", Boolean.TRUE);

            // if there's an error, don't release
            if (ServiceUtil.isError(serviceResults)) {
                return ServiceUtil.returnError(err + ServiceUtil.getErrorMessage(serviceResults));
            }

            return result;
        } catch (GenericServiceException e) {
            Debug.logError(e, e.getMessage(), module);
            return ServiceUtil.returnError(err + e.getMessage());
        }
    }

    public static Map<String, Object> finAccountCapture(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue authTrans = (GenericValue) context.get("authTrans");
        BigDecimal amount = (BigDecimal) context.get("captureAmount");
        String currency = (String) context.get("currency");

        // get the authorization transaction
        if (authTrans == null) {
            authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        }
        if (authTrans == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountCannotCapture", locale));
        }

        // get the auth record
        String finAccountAuthId = authTrans.getString("referenceNum");
        GenericValue finAccountAuth;
        try {
            finAccountAuth = EntityQuery.use(delegator).from("FinAccountAuth").where("finAccountAuthId", finAccountAuthId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        Debug.logInfo("Financial account capture [" + finAccountAuth.get("finAccountId") + "] for the amount of $" +
                amount + " Tx #" + finAccountAuth.get("finAccountAuthId"), module);

        // get the financial account
        GenericValue finAccount;
        try {
            finAccount = finAccountAuth.getRelatedOne("FinAccount", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // make sure authorization has not expired
        Timestamp authExpiration = finAccountAuth.getTimestamp("thruDate");
        if ((authExpiration != null) && (authExpiration.before(UtilDateTime.nowTimestamp()))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountAuthorizationExpired", 
                    UtilMisc.toMap("paymentGatewayResponseId", authTrans.getString("paymentGatewayResponseId"),
                            "authExpiration", authExpiration), locale));
        }

        // make sure the fin account itself has not expired
        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountExpired", 
                    UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
        }
        String finAccountId = finAccount.getString("finAccountId");

        // need the product store ID & party ID
        String orderId = orderPaymentPreference.getString("orderId");
        String productStoreId = null;
        String partyId = null;
        if (orderId != null) {
            OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
            productStoreId = orh.getProductStoreId();

            GenericValue billToParty = orh.getBillToParty();
            if (billToParty != null) {
                partyId = billToParty.getString("partyId");
            }
        }

        // BIG NOTE: make sure the expireFinAccountAuth and finAccountWithdraw services are done in the SAME TRANSACTION
        //(i.e. no require-new-transaction in either of them AND no running async)

        // cancel the authorization before doing the withdraw to avoid problems with way negative available amount on account; should happen in same transaction to avoid conflict problems
        Map<String, Object> releaseResult;
        try {
            releaseResult = dispatcher.runSync("expireFinAccountAuth", UtilMisc.<String, Object>toMap("userLogin", userLogin, "finAccountAuthId", finAccountAuthId));
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (ServiceUtil.isError(releaseResult)) {
            return releaseResult;
        }

        // build the withdraw context
        Map<String, Object> withdrawCtx = new HashMap<String, Object>();
        withdrawCtx.put("finAccountId", finAccountId);
        withdrawCtx.put("productStoreId", productStoreId);
        withdrawCtx.put("currency", currency);
        withdrawCtx.put("partyId", partyId);
        withdrawCtx.put("orderId", orderId);
        withdrawCtx.put("amount", amount);
        withdrawCtx.put("reasonEnumId", "FATR_PURCHASE");
        withdrawCtx.put("requireBalance", Boolean.FALSE); // for captures; if auth passed, allow
        withdrawCtx.put("userLogin", userLogin);

        // call the withdraw service
        Map<String, Object> withdrawResp;
        try {
            withdrawResp = dispatcher.runSync("finAccountWithdraw", withdrawCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (ServiceUtil.isError(withdrawResp)) {
            return withdrawResp;
        }

        // create the capture response
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Boolean processResult = (Boolean) withdrawResp.get("processResult");
        BigDecimal withdrawAmount = (BigDecimal) withdrawResp.get("amount");
        String referenceNum = (String) withdrawResp.get("referenceNum");
        result.put("captureResult", processResult);
        result.put("captureRefNum", referenceNum);
        result.put("captureCode", "C");
        result.put("captureFlag", "1");
        result.put("captureAmount", withdrawAmount);

        return result;
    }

    public static Map<String, Object> finAccountRefund(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        BigDecimal amount = (BigDecimal) context.get("refundAmount");
        String currency = (String) context.get("currency");
        String finAccountId = (String) context.get("finAccountId");

        String productStoreId = null;
        String partyId = null;

        String orderId = null;
        if (orderPaymentPreference != null) {
            orderId = orderPaymentPreference.getString("orderId");
            if (orderId != null) {
                OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
                productStoreId = orh.getProductStoreId();

                GenericValue billToParty = orh.getBillToParty();
                if (billToParty != null) {
                    partyId = billToParty.getString("partyId");
                }
            }
            if (finAccountId == null) {
                finAccountId = orderPaymentPreference.getString("finAccountId");
            }
        }

        if (finAccountId == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", ""), locale));
        }

        // call the deposit service
        Map<String, Object> depositCtx = new HashMap<String, Object>();
        depositCtx.put("finAccountId", finAccountId);
        depositCtx.put("productStoreId", productStoreId);
        depositCtx.put("isRefund", Boolean.TRUE);
        depositCtx.put("currency", currency);
        depositCtx.put("partyId", partyId);
        depositCtx.put("orderId", orderId);
        depositCtx.put("amount", amount);
        depositCtx.put("reasonEnumId", "FATR_REFUND");
        depositCtx.put("userLogin", userLogin);

        Map<String, Object> depositResp;
        try {
            depositResp = dispatcher.runSync("finAccountDeposit", depositCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (ServiceUtil.isError(depositResp)) {
            return depositResp;
        }

        // create the refund response
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Boolean processResult = (Boolean) depositResp.get("processResult");
        BigDecimal depositAmount = (BigDecimal) depositResp.get("amount");
        String referenceNum = (String) depositResp.get("referenceNum");
        result.put("refundResult", processResult);
        result.put("refundRefNum", referenceNum);
        result.put("refundCode", "R");
        result.put("refundFlag", "1");
        result.put("refundAmount", depositAmount);

        return result;
    }

    // base account transaction services
    public static Map<String, Object> finAccountWithdraw(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productStoreId = (String) context.get("productStoreId");
        String finAccountId = (String) context.get("finAccountId");
        String orderItemSeqId = (String) context.get("orderItemSeqId");
        String reasonEnumId = (String) context.get("reasonEnumId");
        String orderId = (String) context.get("orderId");
        Boolean requireBalance = (Boolean) context.get("requireBalance");
        BigDecimal amount = (BigDecimal) context.get("amount");
        if (requireBalance == null) requireBalance = Boolean.TRUE;

        final String WITHDRAWAL = "WITHDRAWAL";

        String partyId = (String) context.get("partyId");
        if (UtilValidate.isEmpty(partyId)) {
            partyId = "_NA_";
        }
        String currencyUom = (String) context.get("currency");
        if (UtilValidate.isEmpty(currencyUom)) {
            currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        // validate the amount
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountMustBePositive", locale));
        }

        GenericValue finAccount;
        try {
            finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // verify we have a financial account
        if (finAccount == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", ""), locale));
        }

        // make sure the fin account itself has not expired
        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountExpired", 
                    UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
        }

        // check the actual balance (excluding authorized amounts) and create the transaction if it is sufficient
        BigDecimal previousBalance = finAccount.getBigDecimal("actualBalance");
        if (previousBalance == null) {
            previousBalance = FinAccountHelper.ZERO;
        }

        BigDecimal balance;
        String refNum;
        Boolean procResult;
        if (requireBalance && previousBalance.compareTo(amount) < 0) {
            procResult = Boolean.FALSE;
            balance = previousBalance;
            refNum = "N/A";
        } else {
            try {
                refNum = FinAccountPaymentServices.createFinAcctPaymentTransaction(delegator, dispatcher, userLogin, amount,
                        productStoreId, partyId, orderId, orderItemSeqId, currencyUom, WITHDRAWAL, finAccountId, reasonEnumId);
                finAccount.refresh();
                balance = finAccount.getBigDecimal("actualBalance");
                procResult = Boolean.TRUE;
            } catch (GeneralException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }

        // make sure balance is not null
        if (balance == null) {
            balance = FinAccountHelper.ZERO;
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("previousBalance", previousBalance);
        result.put("balance", balance);
        result.put("amount", amount);
        result.put("processResult", procResult);
        result.put("referenceNum", refNum);
        return result;
    }

    // base deposit service
    public static Map<String, Object> finAccountDeposit(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productStoreId = (String) context.get("productStoreId");
        String finAccountId = (String) context.get("finAccountId");
        String orderItemSeqId = (String) context.get("orderItemSeqId");
        String reasonEnumId = (String) context.get("reasonEnumId");
        String orderId = (String) context.get("orderId");
        Boolean isRefund = (Boolean) context.get("isRefund");
        BigDecimal amount = (BigDecimal) context.get("amount");

        final String DEPOSIT = isRefund == null || !isRefund ? "DEPOSIT" : "ADJUSTMENT";

        String partyId = (String) context.get("partyId");
        if (UtilValidate.isEmpty(partyId)) {
            partyId = "_NA_";
        }
        String currencyUom = (String) context.get("currency");
        if (UtilValidate.isEmpty(currencyUom)) {
            currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        GenericValue finAccount;
        try {
            finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", finAccountId), locale));
        }

        // verify we have a financial account
        if (finAccount == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", ""), locale));
        }

        // make sure the fin account itself has not expired
        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountExpired", 
                    UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
        }
        Debug.logInfo("Deposit into financial account #" + finAccountId + " [" + amount + "]", module);

        // get the previous balance
        BigDecimal previousBalance = finAccount.getBigDecimal("actualBalance");
        if (previousBalance == null) {
            previousBalance = FinAccountHelper.ZERO;
        }

        // create the transaction
        BigDecimal actualBalance;
        String refNum;
        try {
            refNum = FinAccountPaymentServices.createFinAcctPaymentTransaction(delegator, dispatcher, userLogin, amount,
                    productStoreId, partyId, orderId, orderItemSeqId, currencyUom, DEPOSIT, finAccountId, reasonEnumId);
            finAccount.refresh();
            actualBalance = finAccount.getBigDecimal("actualBalance");
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // make sure balance is not null
        if (actualBalance == null) {
            actualBalance = FinAccountHelper.ZERO;
        } else {
            if (actualBalance.compareTo(BigDecimal.ZERO) < 0) {
                // balance went below zero, set negative pending replenishment status so that no more auths or captures will go through until it is replenished
                try {
                    Map<String, Object> rollbackCtx = UtilMisc.toMap("userLogin", userLogin, "finAccountId", finAccountId, "statusId", "FNACT_NEGPENDREPL");
                    dispatcher.addRollbackService("updateFinAccount", rollbackCtx, true);
                } catch (GenericServiceException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(e.getMessage());
                }
            }
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("previousBalance", previousBalance);
        result.put("balance", actualBalance);
        result.put("amount", amount);
        result.put("processResult", Boolean.TRUE);
        result.put("referenceNum", refNum);
        return result;
    }

    // auto-replenish service (deposit)
    public static Map<String, Object> finAccountReplenish(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productStoreId = (String) context.get("productStoreId");
        String finAccountId = (String) context.get("finAccountId");

        // lookup the FinAccount
        GenericValue finAccount;
        try {
            finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (finAccount == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", finAccountId), locale));
        }
        String currency = finAccount.getString("currencyUomId");
        String statusId = finAccount.getString("statusId");

        // look up the type -- determine auto-replenish is active
        GenericValue finAccountType;
        try {
            finAccountType = finAccount.getRelatedOne("FinAccountType", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        String replenishEnumId = finAccountType.getString("replenishEnumId");
        if (!"FARP_AUTOMATIC".equals(replenishEnumId)) {
            // type does not support auto-replenish
            return ServiceUtil.returnSuccess();
        }

        // attempt to lookup the product store from a previous deposit
        if (productStoreId == null) {
            productStoreId = getLastProductStoreId(delegator, finAccountId);
            if (productStoreId == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingFinAccountCannotBeReplenish", locale));
            }
        }

        // get the product store settings
        GenericValue finAccountSettings;
        Map<String, Object> psfasFindMap = UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "finAccountTypeId", finAccount.getString("finAccountTypeId"));
        try {
            finAccountSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting").where(psfasFindMap).cache().queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (finAccountSettings == null) {
            Debug.logWarning("finAccountReplenish Warning: not replenishing FinAccount [" + finAccountId  + "] because no ProductStoreFinActSetting record found for: " + psfasFindMap, module);
            // no settings; don't replenish
            return ServiceUtil.returnSuccess();
        }

        BigDecimal replenishThreshold = finAccountSettings.getBigDecimal("replenishThreshold");
        if (replenishThreshold == null) {
            Debug.logWarning("finAccountReplenish Warning: not replenishing FinAccount [" + finAccountId  + "] because ProductStoreFinActSetting.replenishThreshold field was null for: " + psfasFindMap, module);
            return ServiceUtil.returnSuccess();
        }

        BigDecimal replenishLevel = finAccount.getBigDecimal("replenishLevel");
        if (replenishLevel == null || replenishLevel.compareTo(BigDecimal.ZERO) == 0) {
            Debug.logWarning("finAccountReplenish Warning: not replenishing FinAccount [" + finAccountId  + "] because FinAccount.replenishLevel field was null or 0", module);
            // no replenish level set; this account goes not support auto-replenish
            return ServiceUtil.returnSuccess();
        }

        // get the current balance
        BigDecimal balance = finAccount.getBigDecimal("actualBalance");

        // see if we are within the threshold for replenishment
        if (balance.compareTo(replenishThreshold) > -1) {
            Debug.logInfo("finAccountReplenish Info: Not replenishing FinAccount [" + finAccountId  + "] because balance [" + balance + "] is greater than the replenishThreshold [" + replenishThreshold + "]", module);
            // not ready
            return ServiceUtil.returnSuccess();
        }

        // configure rollback service to set status to Negative Pending Replenishment
        if ("FNACT_NEGPENDREPL".equals(statusId)) {
            try {
                Map<String, Object> rollbackCtx = UtilMisc.toMap("userLogin", userLogin, "finAccountId", finAccountId, "statusId", "FNACT_NEGPENDREPL");
                dispatcher.addRollbackService("updateFinAccount", rollbackCtx, true);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }

        String replenishMethod = finAccountSettings.getString("replenishMethodEnumId");
        BigDecimal depositAmount;
        if (replenishMethod == null || "FARP_TOP_OFF".equals(replenishMethod)) {
            //the deposit is level - balance (500 - (-10) = 510 || 500 - (10) = 490)
            depositAmount = replenishLevel.subtract(balance);
        } else if ("FARP_REPLENISH_LEVEL".equals(replenishMethod)) {
            //the deposit is replenish-level itself
            depositAmount = replenishLevel;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountUnknownReplenishMethod", locale));
        }

        // get the owner party
        String ownerPartyId = finAccount.getString("ownerPartyId");
        if (ownerPartyId == null) {
            // no owner cannot replenish; (not fatal, just not supported by this account)
            Debug.logWarning("finAccountReplenish Warning: No owner attached to financial account [" + finAccountId + "] cannot auto-replenish", module);
            return ServiceUtil.returnSuccess();
        }

        // get the payment method to use to replenish
        String paymentMethodId = finAccount.getString("replenishPaymentId");
        if (paymentMethodId == null) {
            Debug.logWarning("finAccountReplenish Warning: No payment method (replenishPaymentId) attached to financial account [" + finAccountId + "] cannot auto-replenish", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNoPaymentMethodAssociatedWithReplenishAccount", locale));
        }

        GenericValue paymentMethod;
        try {
            paymentMethod = EntityQuery.use(delegator).from("PaymentMethod").where("paymentMethodId", paymentMethodId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (paymentMethod == null) {
            // no payment methods on file; cannot replenish
            Debug.logWarning("finAccountReplenish Warning: No payment method found for ID [" + paymentMethodId + "] for party [" + ownerPartyId + "] cannot auto-replenish", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountNoPaymentMethodAssociatedWithReplenishAccount", locale));
        }

        // hit the payment method for the amount to replenish
        Map<String, BigDecimal> orderItemMap = UtilMisc.toMap("Auto-Replenishment FA #" + finAccountId, depositAmount);
        Map<String, Object> replOrderCtx = new HashMap<String, Object>();
        replOrderCtx.put("productStoreId", productStoreId);
        replOrderCtx.put("paymentMethodId", paymentMethod.getString("paymentMethodId"));
        replOrderCtx.put("currency", currency);
        replOrderCtx.put("partyId", ownerPartyId);
        replOrderCtx.put("itemMap", orderItemMap);
        replOrderCtx.put("userLogin", userLogin);
        Map<String, Object> replResp;
        try {
            replResp = dispatcher.runSync("createSimpleNonProductSalesOrder", replOrderCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (ServiceUtil.isError(replResp)) {
            return replResp;
        }
        String orderId = (String) replResp.get("orderId");

        // create the deposit
        Map<String, Object> depositCtx = new HashMap<String, Object>();
        depositCtx.put("productStoreId", productStoreId);
        depositCtx.put("finAccountId", finAccountId);
        depositCtx.put("currency", currency);
        depositCtx.put("partyId", ownerPartyId);
        depositCtx.put("orderId", orderId);
        depositCtx.put("orderItemSeqId", "00001"); // always one item on a replish order
        depositCtx.put("amount",  depositAmount);
        depositCtx.put("reasonEnumId", "FATR_REPLENISH");
        depositCtx.put("userLogin", userLogin);
        try {
            Map<String, Object> depositResp = dispatcher.runSync("finAccountDeposit", depositCtx);
            if (ServiceUtil.isError(depositResp)) {
                return depositResp;
            }
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // say we are in good standing again
        if ("FNACT_NEGPENDREPL".equals(statusId)) {
            try {
                Map<String, Object> ufaResp = dispatcher.runSync("updateFinAccount", UtilMisc.<String, Object>toMap("finAccountId", finAccountId, "statusId", "FNACT_ACTIVE", "userLogin", userLogin));
                if (ServiceUtil.isError(ufaResp)) {
                    return ufaResp;
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        }

        return ServiceUtil.returnSuccess();
    }

    private static String getLastProductStoreId(Delegator delegator, String finAccountId) {
        GenericValue trans = null;
        try {
            trans = EntityQuery.use(delegator).from("FinAccountTrans")
                    .where(
                            EntityCondition.makeCondition("finAccountTransTypeId", EntityOperator.EQUALS, "DEPOSIT"),
                            EntityCondition.makeCondition("finAccountId", EntityOperator.EQUALS, finAccountId),
                            EntityCondition.makeCondition("orderId", EntityOperator.NOT_EQUAL, null)
                    ).orderBy("-transactionDate").queryFirst();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        if (trans != null) {
            String orderId = trans.getString("orderId");
            OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
            return orh.getProductStoreId();
        }

        // none found; pick one from our set stores
        try {
            GenericValue store = EntityQuery.use(delegator).from("ProductStore").orderBy("productStoreId").queryFirst();
            if (store != null)
                return store.getString("productStoreId");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        return null;
    }

    private static String createFinAcctPaymentTransaction(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, BigDecimal amount,
            String productStoreId, String partyId, String orderId, String orderItemSeqId, String currencyUom, String txType, String finAccountId, String reasonEnumId) throws GeneralException {

        final String coParty = ProductStoreWorker.getProductStorePayToPartyId(productStoreId, delegator);
        final String paymentMethodType = "FIN_ACCOUNT";

        if (UtilValidate.isEmpty(partyId)) {
            partyId = "_NA_";
        }

        String paymentType;
        String partyIdFrom;
        String partyIdTo;
        BigDecimal paymentAmount;

        // determine the payment type and which direction the parties should go
        if ("DEPOSIT".equals(txType)) {
            paymentType = "RECEIPT";
            partyIdFrom = partyId;
            partyIdTo = coParty;
            paymentAmount = amount;
        } else if ("WITHDRAWAL".equals(txType)) {
            paymentType = "DISBURSEMENT";
            partyIdFrom = coParty;
            partyIdTo = partyId;
            paymentAmount = amount;
        } else if ("ADJUSTMENT".equals(txType)) {
            if (amount.compareTo(BigDecimal.ZERO) < 0) {
                paymentType = "DISBURSEMENT";
                partyIdFrom = coParty;
                partyIdTo = partyId;
                paymentAmount = amount.negate(); // must be positive
            } else {
                paymentType = "RECEIPT";
                partyIdFrom = partyId;
                partyIdTo = coParty;
                paymentAmount = amount;
            }
        } else {
            throw new GeneralException("Unable to create financial account transaction!");
        }

        // payment amount should always be positive; adjustments may
        // create the payment for the transaction
        Map<String, Object> paymentCtx = UtilMisc.<String, Object>toMap("paymentTypeId", paymentType);
        paymentCtx.put("paymentMethodTypeId", paymentMethodType);
        paymentCtx.put("partyIdTo", partyIdTo);
        paymentCtx.put("partyIdFrom", partyIdFrom);
        paymentCtx.put("statusId", "PMNT_RECEIVED");
        paymentCtx.put("currencyUomId", currencyUom);
        paymentCtx.put("amount", paymentAmount);
        paymentCtx.put("userLogin", userLogin);
        paymentCtx.put("paymentRefNum", Long.toString(UtilDateTime.nowTimestamp().getTime()));

        String paymentId;
        Map<String, Object> payResult;
        try {
            payResult = dispatcher.runSync("createPayment", paymentCtx);
        } catch (GenericServiceException e) {
            throw new GeneralException(e);
        }
        if (payResult == null) {
            throw new GeneralException("Unknow error in creating financial account transaction!");
        }
        if (ServiceUtil.isError(payResult)) {
            throw new GeneralException(ServiceUtil.getErrorMessage(payResult));
        }
        paymentId = (String) payResult.get("paymentId");

        // create the initial transaction
        Map<String, Object> transCtx = UtilMisc.<String, Object>toMap("finAccountTransTypeId", txType);
        transCtx.put("finAccountId", finAccountId);
        transCtx.put("partyId", partyId);
        transCtx.put("orderId", orderId);
        transCtx.put("orderItemSeqId", orderItemSeqId);
        transCtx.put("reasonEnumId", reasonEnumId);
        transCtx.put("amount", amount);
        transCtx.put("userLogin", userLogin);
        transCtx.put("paymentId", paymentId);

        Map<String, Object> transResult;
        try {
            transResult = dispatcher.runSync("createFinAccountTrans", transCtx);
        } catch (GenericServiceException e) {
            throw new GeneralException(e);
        }
        if (transResult == null) {
            throw new GeneralException("Unknown error in creating financial account transaction!");
        }
        if (ServiceUtil.isError(transResult)) {
            throw new GeneralException(ServiceUtil.getErrorMessage(transResult));
        }

        return (String) transResult.get("finAccountTransId");
    }
}
