/*
 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.ofbiz.accounting.finaccount;

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

import javolution.util.FastMap;

import org.ofbiz.accounting.payment.PaymentGatewayServices;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.entity.util.EntityUtilProperties;
import org.ofbiz.order.finaccount.FinAccountHelper;
import org.ofbiz.order.order.OrderReadHelper;
import org.ofbiz.product.store.ProductStoreWorker;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.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 = FastMap.newInstance();
        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 = FastMap.newInstance();
        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.properties", "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.properties", "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 = FastMap.newInstance();
        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 = FastMap.newInstance();
        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");
    }
}
