/*******************************************************************************
 * 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.payment;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

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.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;


public class GiftCertificateServices {

    public static final String module = GiftCertificateServices.class.getName();
    public static final String resourceError = "AccountingErrorUiLabels";
    public static final String resourceOrderError = "OrderErrorUiLabels";
    // These are default settings, in case ProductStoreFinActSetting does not have them
    public static final int CARD_NUMBER_LENGTH = 14;
    public static final int PIN_NUMBER_LENGTH = 6;

    public static BigDecimal ZERO = BigDecimal.ZERO;

    // Base Gift Certificate Services
    public static Map<String, Object> createGiftCertificate(DispatchContext dctx, Map<String, ? extends 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");
        BigDecimal initialAmount = (BigDecimal) context.get("initialAmount");
        String currency = (String) context.get("currency");
        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);
        }

        String cardNumber = null;
        String pinNumber = null;
        String refNum = null;
        String finAccountId = null;
        try {
            final String accountName = "Gift Certificate Account";
            final String deposit = "DEPOSIT";

            GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
                    .where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
                    .cache().queryOne();
            Map<String, Object> acctResult = null;

            if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
                // TODO: move this code to createFinAccountForStore as well
                int cardNumberLength = CARD_NUMBER_LENGTH;
                int pinNumberLength = PIN_NUMBER_LENGTH;
                if (giftCertSettings.getLong("accountCodeLength") != null) {
                    cardNumberLength = giftCertSettings.getLong("accountCodeLength").intValue();
                }
                if (giftCertSettings.getLong("pinCodeLength") != null) {
                    pinNumberLength = giftCertSettings.getLong("pinCodeLength").intValue();
                }
                cardNumber = generateNumber(delegator, cardNumberLength, true);
                pinNumber = generateNumber(delegator, pinNumberLength, false);

                // in this case, the card number is the finAccountId
                finAccountId = cardNumber;

                // create the FinAccount
                Map<String, Object> acctCtx = UtilMisc.<String, Object>toMap("finAccountId", finAccountId);
                acctCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
                acctCtx.put("finAccountName", accountName);
                acctCtx.put("finAccountCode", pinNumber);
                acctCtx.put("userLogin", userLogin);
                acctResult = dispatcher.runSync("createFinAccount", acctCtx);
            } else {
                Map<String, Object> createAccountCtx = new HashMap<String, Object>();
                createAccountCtx.put("ownerPartyId", partyId);
                createAccountCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
                createAccountCtx.put("productStoreId", productStoreId);
                createAccountCtx.put("currencyUomId", currency);
                createAccountCtx.put("finAccountName", accountName + "for party ["+partyId+"]");
                createAccountCtx.put("userLogin", userLogin);
                acctResult = dispatcher.runSync("createFinAccountForStore", createAccountCtx);
                if (acctResult.get("finAccountId") != null) {
                    finAccountId = cardNumber = (String) acctResult.get("finAccountId");
                }
                if (acctResult.get("finAccountCode") != null) {
                    cardNumber = (String) acctResult.get("finAccountCode");
                }
            }

            if (ServiceUtil.isError(acctResult)) {
                String error = ServiceUtil.getErrorMessage(acctResult);
                return ServiceUtil.returnError(error);
            }

            // create the initial (deposit) transaction
            // do something tricky here: run as the "system" user
            // that can actually create a financial account transaction
            GenericValue permUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").cache().queryOne();
            refNum = createTransaction(delegator, dispatcher, permUserLogin, initialAmount, productStoreId, 
                    partyId, currencyUom, deposit, finAccountId, locale);

        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCreationError", locale));
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCreationError", locale));
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("cardNumber", cardNumber);
        result.put("pinNumber", pinNumber);
        result.put("initialAmount", initialAmount);
        result.put("processResult", Boolean.TRUE);
        result.put("responseCode", "1");
        result.put("referenceNum", refNum);
        Debug.logInfo("Create GC Result - " + result, module);
        return result;
    }

    public static Map<String, Object> addFundsToGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        final String deposit = "DEPOSIT";

        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productStoreId = (String) context.get("productStoreId");
        String cardNumber = (String) context.get("cardNumber");
        String pinNumber = (String) context.get("pinNumber");
        BigDecimal amount = (BigDecimal) context.get("amount");

        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);
        }

        String finAccountId = null;
        GenericValue finAccount = null;
         // validate the pin if the store requires it and figure out the finAccountId from card number
        try {
            GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
                    .where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
                    .cache().queryOne();
            if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
                if (!validatePin(delegator, cardNumber, pinNumber)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "AccountingGiftCerticateNumberPinNotValid", locale));
                }
                finAccountId = cardNumber;
            } else {
                finAccount = FinAccountHelper.getFinAccountFromCode(cardNumber, delegator);
                if (finAccount != null) {
                    finAccountId = finAccount.getString("finAccountId");
                }
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountSetting", 
                    UtilMisc.toMap("productStoreId", productStoreId, 
                            "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
        }

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

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

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

        // create the transaction
        BigDecimal balance = ZERO;
        String refNum = null;
        try {
            refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount, productStoreId, partyId,
                    currencyUom, deposit, finAccountId, locale);
            finAccount.refresh();
            balance = finAccount.getBigDecimal("availableBalance");
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("previousBalance", previousBalance);
        result.put("balance", balance);
        result.put("amount", amount);
        result.put("processResult", Boolean.TRUE);
        result.put("responseCode", "1");
        result.put("referenceNum", refNum);
        Debug.logInfo("Add Funds GC Result - " + result, module);
        return result;
    }

    public static Map<String, Object> redeemGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        final String withdrawl = "WITHDRAWAL";
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String productStoreId = (String) context.get("productStoreId");
        String cardNumber = (String) context.get("cardNumber");
        String pinNumber = (String) context.get("pinNumber");
        BigDecimal amount = (BigDecimal) context.get("amount");

        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(ZERO) < 0) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountMustBePositive", locale));
        }

        // validate the pin if the store requires it
        try {
            GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
                    .where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
                    .cache().queryOne();
            if ("Y".equals(giftCertSettings.getString("requirePinCode")) && !validatePin(delegator, cardNumber, pinNumber)) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberPinNotValid", locale));
            }
        } catch (GenericEntityException ex) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountSetting", 
                    UtilMisc.toMap("productStoreId", productStoreId, 
                            "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
        }
        Debug.logInfo("Attempting to redeem GC for " + amount, module);

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

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

        BigDecimal balance = ZERO;
        String refNum = null;
        Boolean procResult;
        if (previousBalance.compareTo(amount) >= 0) {
            try {
                refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount, productStoreId,
                        partyId, currencyUom, withdrawl, cardNumber, locale);
                finAccount.refresh();
                balance = finAccount.get("availableBalance") == null ? ZERO : finAccount.getBigDecimal("availableBalance");
                procResult = Boolean.TRUE;
            } catch (GeneralException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(e.getMessage());
            }
        } else {
            procResult = Boolean.FALSE;
            balance = previousBalance;
            refNum = "N/A";
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("previousBalance", previousBalance);
        result.put("balance", balance);
        result.put("amount", amount);
        result.put("processResult", procResult);
        result.put("responseCode", "2");
        result.put("referenceNum", refNum);
        Debug.logInfo("Redeem GC Result - " + result, module);
        return result;
    }

    public static Map<String, Object> checkGiftCertificateBalance(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        String cardNumber = (String) context.get("cardNumber");
        String pinNumber = (String) context.get("pinNumber");
        Locale locale = (Locale) context.get("locale");

        // validate the pin
        if (!validatePin(delegator, cardNumber, pinNumber)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberPinNotValid", locale));
        }

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

        // TODO: get the real currency from context
        // get the balance
        BigDecimal balance = finAccount.get("availableBalance") == null ? ZERO : finAccount.getBigDecimal("availableBalance");

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("balance", balance);
        Debug.logInfo("GC Balance Result - " + result, module);
        return result;
    }

    // Fullfilment Services
    public static Map<String, Object> giftCertificateProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        BigDecimal amount = (BigDecimal) context.get("processAmount");
        String currency = (String) context.get("currency");
        // make sure we have a currency
        if (currency == null) {
            currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

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

        // get the gift certificate and its authorization from the authorization
        String finAccountAuthId = authTransaction.getString("referenceNum");
        try {
            GenericValue finAccountAuth = EntityQuery.use(delegator).from("FinAccountAuth").where("finAccountAuthId", finAccountAuthId).queryOne();
            GenericValue giftCard = finAccountAuth.getRelatedOne("FinAccount", false);
            // 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", authTransaction.getString("paymentGatewayResponseId"),
                                "authExpiration", authExpiration), locale));
            }
            // make sure the fin account itself has not expired
            if ((giftCard.getTimestamp("thruDate") != null) && (giftCard.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberExpired", 
                        UtilMisc.toMap("thruDate", giftCard.getTimestamp("thruDate")), locale));
            }

            // obtain the order information
            OrderReadHelper orh = new OrderReadHelper(delegator, orderPaymentPreference.getString("orderId"));

            Map<String, Object> redeemCtx = new HashMap<String, Object>();
            redeemCtx.put("userLogin", userLogin);
            redeemCtx.put("productStoreId", orh.getProductStoreId());
            redeemCtx.put("cardNumber", giftCard.get("finAccountId"));
            redeemCtx.put("pinNumber", giftCard.get("finAccountCode"));
            redeemCtx.put("currency", currency);
            if (orh.getBillToParty() != null) {
                redeemCtx.put("partyId", orh.getBillToParty().get("partyId"));
            }
            redeemCtx.put("amount", amount);

            // invoke the redeem service
            Map<String, Object> redeemResult = null;
            redeemResult = dispatcher.runSync("redeemGiftCertificate", redeemCtx);
            if (ServiceUtil.isError(redeemResult)) {
                return redeemResult;
            }

            // now release the authorization should this use the gift card release service?
            Map<String, Object> releaseResult = dispatcher.runSync("expireFinAccountAuth", 
                    UtilMisc.<String, Object>toMap("userLogin", userLogin, "finAccountAuthId", finAccountAuthId));
            if (ServiceUtil.isError(releaseResult)) {
                return releaseResult;
            }

            String authRefNum = authTransaction.getString("referenceNum");
            Map<String, Object> result = ServiceUtil.returnSuccess();
            if (redeemResult != null) {
                Boolean processResult = (Boolean) redeemResult.get("processResult");
                result.put("processAmount", amount);
                result.put("captureResult", processResult);
                result.put("captureCode", "C");
                result.put("captureRefNum", redeemResult.get("referenceNum"));
                result.put("authRefNum", authRefNum);
            }

            return result;

        } catch (GenericEntityException ex) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotProcess", 
                    UtilMisc.toMap("errorString", ex.getMessage()), locale));
        } catch (GenericServiceException ex) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotProcess", 
                    UtilMisc.toMap("errorString", ex.getMessage()), locale));
        }
}


    public static Map<String, Object> giftCertificateAuthorize(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        GenericValue giftCard = (GenericValue) context.get("giftCard");
        String currency = (String) context.get("currency");
        String orderId = (String) context.get("orderId");
        BigDecimal amount = (BigDecimal) context.get("processAmount");

        // make sure we have a currency
        if (currency == null) {
            currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        // obtain the order information
        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
        String productStoreId = orh.getProductStoreId();
        try {
            // if the store requires pin codes, then validate pin code against card number, and the gift certificate's finAccountId is the gift card's card number
            // otherwise, the gift card's card number is an ecrypted string, which must be decoded to find the FinAccount
            GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
                    .where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
                    .cache().queryOne();
            GenericValue finAccount = null;
            String finAccountId = null;
            if (UtilValidate.isNotEmpty(giftCertSettings)) {
                if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
                    if (validatePin(delegator, giftCard.getString("cardNumber"), giftCard.getString("pinNumber"))) {
                        finAccountId = giftCard.getString("cardNumber");
                        finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
                    }
                } else {
                        finAccount = FinAccountHelper.getFinAccountFromCode(giftCard.getString("cardNumber"), delegator);
                        if (finAccount == null) {
                            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                                    "AccountingGiftCerticateNumberNotFound", 
                                    UtilMisc.toMap("finAccountId", ""), locale));
                        }
                        finAccountId = finAccount.getString("finAccountId");
                }
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingFinAccountSetting", 
                        UtilMisc.toMap("productStoreId", productStoreId, 
                                "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
            }

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

            // check for expiration date
            if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberExpired", 
                        UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
            }

            // 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");
            Boolean processResult = null;
            String refNum = null;
            Map<String, Object> result = ServiceUtil.returnSuccess();

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

            // if availableBalance equal to or greater than amount, then auth
            if (UtilValidate.isNotEmpty(availableBalance) && availableBalance.compareTo(amount) >= 0) {
                Timestamp thruDate = null;
                if (giftCertSettings.getLong("authValidDays") != null) {
                    thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), giftCertSettings.getLong("authValidDays"));
                }
                Map<String, Object> tmpResult = dispatcher.runSync("createFinAccountAuth", 
                        UtilMisc.<String, Object>toMap("finAccountId", finAccountId, 
                                "amount", amount, "currencyUomId", currency,
                                "thruDate", thruDate, "userLogin", userLogin));
                if (ServiceUtil.isError(tmpResult)) {
                    return tmpResult;
                } else {
                    refNum = (String) tmpResult.get("finAccountAuthId");
                    processResult = Boolean.TRUE;
                }
            } else {
                Debug.logError("Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "]", module);
                refNum = "N/A";      // a refNum is always required from authorization
                processResult = Boolean.FALSE;
            }

            result.put("processAmount", amount);
            result.put("authResult", processResult);
            result.put("processAmount", amount);
            result.put("authFlag", "2");
            result.put("authCode", "A");
            result.put("captureCode", "C");
            result.put("authRefNum", refNum);

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

    public static Map<String, Object> giftCertificateRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        String currency = (String) context.get("currency");
        BigDecimal amount = (BigDecimal) context.get("refundAmount");
        Locale locale = (Locale) context.get("locale");
        return giftCertificateRestore(dctx, userLogin, paymentPref, amount, currency, "refund", locale);
    }

    public static Map<String, Object> giftCertificateRelease(DispatchContext dctx, Map<String, ? extends 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, 
                "AccountingGiftCerticateNumberCannotBeExpired", 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.<String, Object>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());
        }
    }

    private static Map<String, Object> giftCertificateRestore(DispatchContext dctx, GenericValue userLogin, GenericValue paymentPref, 
            BigDecimal amount, String currency, String resultPrefix, Locale locale) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        
        // get the orderId for tracking
        String orderId = paymentPref.getString("orderId");
        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
        String productStoreId = orh.getProductStoreId();

        // party ID for tracking
        GenericValue placingParty = orh.getPlacingParty();
        String partyId = null;
        if (placingParty != null) {
            partyId = placingParty.getString("partyId");
        }

        // get the GiftCard VO
        GenericValue giftCard = null;
        try {
            giftCard = paymentPref.getRelatedOne("GiftCard", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get GiftCard from OrderPaymentPreference", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotLocateItFromOrderPaymentPreference", locale));
        }

        if (giftCard == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotRelease", locale));
        }

        // make sure we have a currency
        if (currency == null) {
            currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        Map<String, Object> refundCtx = new HashMap<String, Object>();
        refundCtx.put("productStoreId", productStoreId);
        refundCtx.put("currency", currency);
        refundCtx.put("partyId", partyId);
        refundCtx.put("cardNumber", giftCard.get("cardNumber"));
        refundCtx.put("pinNumber", giftCard.get("pinNumber"));
        refundCtx.put("amount", amount);
        refundCtx.put("userLogin", userLogin);

        Map<String, Object> restoreGcResult = null;
        try {
            restoreGcResult = dispatcher.runSync("addFundsToGiftCertificate", refundCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberRefundCallError", locale));
        }
        if (ServiceUtil.isError(restoreGcResult)) {
            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(restoreGcResult));
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        if (restoreGcResult != null) {
            Boolean processResult = (Boolean) restoreGcResult.get("processResult");
            result.put(resultPrefix + "Amount", amount);
            result.put(resultPrefix + "Result", processResult);
            result.put(resultPrefix + "Code", "R");
            result.put(resultPrefix + "Flag", restoreGcResult.get("responseCode"));
            result.put(resultPrefix + "RefNum", restoreGcResult.get("referenceNum"));
        }

        return result;
    }

    public static Map<String, Object> giftCertificatePurchase(DispatchContext dctx, Map<String, ? extends Object> context) {
        // this service should always be called via FULFILLMENT_EXTASYNC
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue orderItem = (GenericValue) context.get("orderItem");
        Locale locale = (Locale) context.get("locale");

        // order ID for tracking
        String orderId = orderItem.getString("orderId");

        // the order header for store info
        GenericValue orderHeader = null;
        try {
            orderHeader = orderItem.getRelatedOne("OrderHeader", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "OrderCannotGetOrderHeader", UtilMisc.toMap("orderId", orderId), locale));
        }

        // get the order read helper
        OrderReadHelper orh = new OrderReadHelper(orderHeader);

        // get the currency
        String currency = orh.getCurrency();

        // make sure we have a currency
        if (currency == null) {
            currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        // get the product store
        String productStoreId = null;
        if (orderHeader != null) {
            productStoreId = orh.getProductStoreId();
        }
        if (productStoreId == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotProcess",
                    UtilMisc.toMap("orderId", orderId), locale));
        }

        // party ID for tracking
        GenericValue placingParty = orh.getPlacingParty();
        String partyId = null;
        if (placingParty != null) {
            partyId = placingParty.getString("partyId");
        }

        // amount/quantity of the gift card(s)
        BigDecimal amount = orderItem.getBigDecimal("unitPrice");
        BigDecimal quantity = orderItem.getBigDecimal("quantity");

        // the product entity needed for information
        GenericValue product = null;
        try {
            product = orderItem.getRelatedOne("Product", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get Product from OrderItem", module);
        }
        if (product == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotFulfill", locale));
        }

        // Gift certificate settings are per store in this entity
        GenericValue giftCertSettings = null;
        try {
            giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
                    .where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
                    .cache().queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get Product Store FinAccount settings for " + FinAccountHelper.giftCertFinAccountTypeId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountSetting", 
                    UtilMisc.toMap("productStoreId", productStoreId, 
                            "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale) + ": " + e.getMessage());
        }

        // survey information
        String surveyId = giftCertSettings.getString("purchaseSurveyId");

        // get the survey response
        GenericValue surveyResponse = null;
        try {
            // there should be only one
            surveyResponse = EntityQuery.use(delegator).from("SurveyResponse")
                    .where("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId)
                    .orderBy("-responseDate").queryFirst();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotFulfill", locale));
        }
        if (surveyResponse == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotFulfill", locale));
        }

        // get the response answers
        List<GenericValue> responseAnswers = null;
        try {
            responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer", null, null, false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotFulfillFromSurveyAnswers", locale));
        }

        // make a map of answer info
        Map<String, Object> answerMap = new HashMap<String, Object>();
        if (responseAnswers != null) {
            for (GenericValue answer : responseAnswers) {
                GenericValue question = null;
                try {
                    question = answer.getRelatedOne("SurveyQuestion", false);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "AccountingGiftCerticateNumberCannotFulfillFromSurveyAnswers", locale));
                }
                if (question != null) {
                    String desc = question.getString("description");
                    String ans = answer.getString("textResponse");  // only support text response types for now
                    answerMap.put(desc, ans);
                }
            }
        }

        // get the send to email address - key defined in product store settings entity
        String sendToKey = giftCertSettings.getString("purchSurveySendTo");
        String sendToEmail = (String) answerMap.get(sendToKey);

        // get the copyMe flag and set the order email address
        String orderEmails = orh.getOrderEmailString();
        String copyMeField = giftCertSettings.getString("purchSurveyCopyMe");
        String copyMeResp = copyMeField != null ? (String) answerMap.get(copyMeField) : null;
        boolean copyMe = (UtilValidate.isNotEmpty(copyMeField)
                && UtilValidate.isNotEmpty(copyMeResp) && "true".equalsIgnoreCase(copyMeResp)) ? true : false;

        int qtyLoop = quantity.intValue();
        for (int i = 0; i < qtyLoop; i++) {
            // create a gift certificate
            Map<String, Object> createGcCtx = new HashMap<String, Object>();
            createGcCtx.put("productStoreId", productStoreId);
            createGcCtx.put("currency", currency);
            createGcCtx.put("partyId", partyId);
            createGcCtx.put("initialAmount", amount);
            createGcCtx.put("userLogin", userLogin);

            Map<String, Object> createGcResult = null;
            try {
                createGcResult = dispatcher.runSync("createGiftCertificate", createGcCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberCreationError", locale) + e.getMessage());
            }
            if (ServiceUtil.isError(createGcResult)) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberCreationError", locale) 
                        + ServiceUtil.getErrorMessage(createGcResult));
            }

            // create the fulfillment record
            Map<String, Object> gcFulFill = new HashMap<String, Object>();
            gcFulFill.put("typeEnumId", "GC_ACTIVATE");
            gcFulFill.put("partyId", partyId);
            gcFulFill.put("orderId", orderId);
            gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
            gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
            gcFulFill.put("cardNumber", createGcResult.get("cardNumber"));
            gcFulFill.put("pinNumber", createGcResult.get("pinNumber"));
            gcFulFill.put("amount", createGcResult.get("initialAmount"));
            gcFulFill.put("responseCode", createGcResult.get("responseCode"));
            gcFulFill.put("referenceNum", createGcResult.get("referenceNum"));
            gcFulFill.put("userLogin", userLogin);
            try {
                dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
                        UtilMisc.toMap("errorString", e.getMessage()), locale));
            }

            // add some information to the answerMap for the email
            answerMap.put("cardNumber", createGcResult.get("cardNumber"));
            answerMap.put("pinNumber", createGcResult.get("pinNumber"));
            answerMap.put("amount", createGcResult.get("initialAmount"));

            // get the email setting for this email type
            GenericValue productStoreEmail = null;
            String emailType = "PRDS_GC_PURCHASE";
            try {
                productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", emailType).queryOne();
            } catch (GenericEntityException e) {
                Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
            }
            if (productStoreEmail == null) {
                Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
            } else {
                answerMap.put("locale", locale);

                // set the bcc address(s)
                String bcc = productStoreEmail.getString("bccAddress");
                if (copyMe) {
                    if (UtilValidate.isNotEmpty(bcc)) {
                        bcc = bcc + "," + orderEmails;
                    } else {
                        bcc = orderEmails;
                    }
                }
                Map<String, Object> emailCtx = new HashMap<String, Object>();
                String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                if (UtilValidate.isEmpty(bodyScreenLocation)) {
                    bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
                }
                emailCtx.put("bodyScreenUri", bodyScreenLocation);
                emailCtx.put("bodyParameters", answerMap);
                emailCtx.put("sendTo", sendToEmail);
                emailCtx.put("contentType", productStoreEmail.get("contentType"));
                emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
                emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
                emailCtx.put("sendBcc", bcc);
                emailCtx.put("subject", productStoreEmail.getString("subject"));
                emailCtx.put("userLogin", userLogin);
                
                // send off the email async so we will retry on failed attempts
                // SC 20060405: Changed to runSync because runAsync kept getting an error:
                // Problem serializing service attributes (Cannot serialize object of class java.util.PropertyResourceBundle)
                try {
                    dispatcher.runAsync("sendMailFromScreen", emailCtx);
                } catch (GenericServiceException e) {
                    Debug.logError(e, "Problem sending mail", module);
                    // this is fatal; we will rollback and try again later
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "AccountingGiftCerticateNumberCannotSendEmailNotice",
                            UtilMisc.toMap("errorString", e.toString()), locale));
                }
            }
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> giftCertificateReload(DispatchContext dctx, Map<String, ? extends Object> context) {
        // this service should always be called via FULFILLMENT_EXTSYNC
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue orderItem = (GenericValue) context.get("orderItem");
        Locale locale = (Locale) context.get("locale");

        // order ID for tracking
        String orderId = orderItem.getString("orderId");

        // the order header for store info
        GenericValue orderHeader = null;
        try {
            orderHeader = orderItem.getRelatedOne("OrderHeader", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "OrderCannotGetOrderHeader", UtilMisc.toMap("orderId", orderId), locale));
        }

        // get the order read helper
        OrderReadHelper orh = new OrderReadHelper(orderHeader);

        // get the currency
        String currency = orh.getCurrency();

        // make sure we have a currency
        if (currency == null) {
            currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
        }

        // get the product store
        String productStoreId = null;
        if (orderHeader != null) {
            productStoreId = orh.getProductStoreId();
        }
        if (productStoreId == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "AccountingGiftCerticateNumberCannotReload", UtilMisc.toMap("orderId", orderId), locale));
        }

        // payment config
        GenericValue paymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, "GIFT_CARD", null, true);
        String paymentConfig = null;
        if (paymentSetting != null) {
            paymentConfig = paymentSetting.getString("paymentPropertiesPath");
        }
        if (paymentConfig == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "AccountingGiftCerticateNumberCannotGetPaymentConfiguration", locale));
        }

        // party ID for tracking
        GenericValue placingParty = orh.getPlacingParty();
        String partyId = null;
        if (placingParty != null) {
            partyId = placingParty.getString("partyId");
        }

        // amount of the gift card reload
        BigDecimal amount = orderItem.getBigDecimal("unitPrice");

        // survey information
        String surveyId = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.surveyId", delegator);

        // get the survey response
        GenericValue surveyResponse = null;
        try {
            // there should be only one
            surveyResponse = EntityQuery.use(delegator).from("SurveyResponse")
                    .where("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId)
                    .orderBy("-responseDate").queryFirst();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "AccountingGiftCerticateNumberCannotReload", locale));
        }

        // get the response answers
        List<GenericValue> responseAnswers = null;
        try {
            responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer", null, null, false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "AccountingGiftCerticateNumberCannotReloadFromSurveyAnswers", locale));
        }

        // make a map of answer info
        Map<String, Object> answerMap = new HashMap<String, Object>();
        if (responseAnswers != null) {
            for (GenericValue answer : responseAnswers) {
                GenericValue question = null;
                try {
                    question = answer.getRelatedOne("SurveyQuestion", false);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                            "AccountingGiftCerticateNumberCannotReloadFromSurveyAnswers", locale));
                }
                if (question != null) {
                    String desc = question.getString("description");
                    String ans = answer.getString("textResponse");  // only support text response types for now
                    answerMap.put(desc, ans);
                }
            }
        }

        String cardNumberKey = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.cardNumber", delegator);
        String pinNumberKey = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.pinNumber", delegator);
        String cardNumber = (String) answerMap.get(cardNumberKey);
        String pinNumber = (String) answerMap.get(pinNumberKey);

        // reload the gift card
        Map<String, Object> reloadCtx = new HashMap<String, Object>();
        reloadCtx.put("productStoreId", productStoreId);
        reloadCtx.put("currency", currency);
        reloadCtx.put("partyId", partyId);
        reloadCtx.put("cardNumber", cardNumber);
        reloadCtx.put("pinNumber", pinNumber);
        reloadCtx.put("amount", amount);
        reloadCtx.put("userLogin", userLogin);

        String errorMessage = null;
        Map<String, Object> reloadGcResult = null;
        try {
            reloadGcResult = dispatcher.runSync("addFundsToGiftCertificate", reloadCtx);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            errorMessage = "Unable to call reload service!";
        }
        if (ServiceUtil.isError(reloadGcResult)) {
            errorMessage = ServiceUtil.getErrorMessage(reloadGcResult);
        }

        // create the fulfillment record
        Map<String, Object> gcFulFill = new HashMap<String, Object>();
        gcFulFill.put("typeEnumId", "GC_RELOAD");
        gcFulFill.put("userLogin", userLogin);
        gcFulFill.put("partyId", partyId);
        gcFulFill.put("orderId", orderId);
        gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
        gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
        gcFulFill.put("cardNumber", cardNumber);
        gcFulFill.put("pinNumber", pinNumber);
        gcFulFill.put("amount", amount);
        if (reloadGcResult != null) {
            gcFulFill.put("responseCode", reloadGcResult.get("responseCode"));
            gcFulFill.put("referenceNum", reloadGcResult.get("referenceNum"));
        }
        try {
            dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
                    UtilMisc.toMap("errorString", e.getMessage()), locale));
        }

        if (errorMessage != null) {
            // there was a problem
            Debug.logError("Reload Failed Need to Refund : " + reloadGcResult, module);

            // process the return
            try {
                Map<String, Object> refundCtx = UtilMisc.toMap("orderItem", orderItem, 
                        "partyId", partyId, "userLogin", userLogin);
                dispatcher.runAsync("refundGcPurchase", refundCtx, null, true, 300, true);
            } catch (GenericServiceException e) {
                Debug.logError(e, "ERROR! Unable to call create refund service; this failed reload will NOT be refunded", module);
            }

            return ServiceUtil.returnError(errorMessage);
        }

        // add some information to the answerMap for the email
        answerMap.put("processResult", reloadGcResult.get("processResult"));
        answerMap.put("responseCode", reloadGcResult.get("responseCode"));
        answerMap.put("previousAmount", reloadGcResult.get("previousBalance"));
        answerMap.put("amount", reloadGcResult.get("amount"));

        // get the email setting for this email type
        GenericValue productStoreEmail = null;
        String emailType = "PRDS_GC_RELOAD";
        try {
            productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", emailType).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
        }
        if (productStoreEmail == null) {
            Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
        } else {
            answerMap.put("locale", locale);

            Map<String, Object> emailCtx = new HashMap<String, Object>();
            String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
            if (UtilValidate.isEmpty(bodyScreenLocation)) {
                bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
            }
            emailCtx.put("bodyScreenUri", bodyScreenLocation);
            emailCtx.put("bodyParameters", answerMap);
            emailCtx.put("sendTo", orh.getOrderEmailString());
            emailCtx.put("contentType", productStoreEmail.get("contentType"));
            emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
            emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
            emailCtx.put("sendBcc", productStoreEmail.get("bccAddress"));
            emailCtx.put("subject", productStoreEmail.getString("subject"));
            emailCtx.put("userLogin", userLogin);

            // send off the email async so we will retry on failed attempts
            try {
                dispatcher.runAsync("sendMailFromScreen", emailCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem sending mail", module);
                // this is fatal; we will rollback and try again later
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingGiftCerticateNumberCannotSendEmailNotice",
                        UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        return ServiceUtil.returnSuccess();
    }

    // Tracking Service
    public static Map<String, Object> createFulfillmentRecord(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        // create the fulfillment record
        GenericValue gcFulFill = delegator.makeValue("GiftCardFulfillment");
        gcFulFill.set("fulfillmentId", delegator.getNextSeqId("GiftCardFulfillment"));
        gcFulFill.set("typeEnumId", context.get("typeEnumId"));
        gcFulFill.set("merchantId", context.get("merchantId"));
        gcFulFill.set("partyId", context.get("partyId"));
        gcFulFill.set("orderId", context.get("orderId"));
        gcFulFill.set("orderItemSeqId", context.get("orderItemSeqId"));
        gcFulFill.set("surveyResponseId", context.get("surveyResponseId"));
        gcFulFill.set("cardNumber", context.get("cardNumber"));
        gcFulFill.set("pinNumber", context.get("pinNumber"));
        gcFulFill.set("amount", context.get("amount"));
        gcFulFill.set("responseCode", context.get("responseCode"));
        gcFulFill.set("referenceNum", context.get("referenceNum"));
        gcFulFill.set("authCode", context.get("authCode"));
        gcFulFill.set("fulfillmentDate", UtilDateTime.nowTimestamp());
        try {
            delegator.create(gcFulFill);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
                    UtilMisc.toMap("errorString", e.toString()), locale));
        }
        return ServiceUtil.returnSuccess();
    }

    // Refund Service
    public static Map<String, Object> refundGcPurchase(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue orderItem = (GenericValue) context.get("orderItem");
        String partyId = (String) context.get("partyId");
        Locale locale = (Locale) context.get("locale");

        // refresh the item object for status changes
        try {
            orderItem.refresh();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        Map<String, Object> returnableInfo = null;
        try {
            returnableInfo = dispatcher.runSync("getReturnableQuantity", UtilMisc.toMap("orderItem", orderItem, 
                    "userLogin", userLogin));
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                    "OrderErrorUnableToGetReturnItemInformation", locale));
        }

        if (returnableInfo != null) {
            BigDecimal returnableQuantity = (BigDecimal) returnableInfo.get("returnableQuantity");
            BigDecimal returnablePrice = (BigDecimal) returnableInfo.get("returnablePrice");
            Debug.logInfo("Returnable INFO : " + returnableQuantity + " @ " + returnablePrice + " :: " + orderItem, module);

            // create the return header
            Map<String, Object> returnHeaderInfo = new HashMap<String, Object>();
            returnHeaderInfo.put("fromPartyId", partyId);
            returnHeaderInfo.put("userLogin", userLogin);
            Map<String, Object> returnHeaderResp = null;
            try {
                returnHeaderResp = dispatcher.runSync("createReturnHeader", returnHeaderInfo);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorUnableToCreateReturnHeader", locale));
            }

            if (returnHeaderResp != null) {
                String errorMessage = ServiceUtil.getErrorMessage(returnHeaderResp);
                if (errorMessage != null) {
                    return ServiceUtil.returnError(errorMessage);
                }
            }

            String returnId = null;
            if (returnHeaderResp != null) {
                returnId = (String) returnHeaderResp.get("returnId");
            }

            if (returnId == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorCreateReturnHeaderWithoutId", locale));
            }

            // create the return item
            Map<String, Object> returnItemInfo = new HashMap<String, Object>();
            returnItemInfo.put("returnId", returnId);
            returnItemInfo.put("returnReasonId", "RTN_DIG_FILL_FAIL");
            returnItemInfo.put("returnTypeId", "RTN_REFUND");
            returnItemInfo.put("returnItemType", "ITEM");
            returnItemInfo.put("description", orderItem.get("itemDescription"));
            returnItemInfo.put("orderId", orderItem.get("orderId"));
            returnItemInfo.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
            returnItemInfo.put("returnQuantity", returnableQuantity);
            returnItemInfo.put("returnPrice", returnablePrice);
            returnItemInfo.put("userLogin", userLogin);
            Map<String, Object> returnItemResp = null;
            try {
                returnItemResp = dispatcher.runSync("createReturnItem", returnItemInfo);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorUnableToCreateReturnItem", locale));
            }

            if (returnItemResp != null) {
                String errorMessage = ServiceUtil.getErrorMessage(returnItemResp);
                if (errorMessage != null) {
                    return ServiceUtil.returnError(errorMessage);
                }
            }

            String returnItemSeqId = null;
            if (returnItemResp != null) {
                returnItemSeqId = (String) returnItemResp.get("returnItemSeqId");
            }

            if (returnItemSeqId == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorCreateReturnItemWithoutId", locale));
            } else {
                Debug.logVerbose("Created return item : " + returnId + " / " + returnItemSeqId, module);
            }

            // need the system userLogin to "fake" out the update service
            GenericValue admin = null;
            try {
                admin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorUnableToUpdateReturnHeaderStatusWithoutUserLogin", locale));
            }

            // update the status to received so it can process
            Map<String, Object> updateReturnInfo = new HashMap<String, Object>();
            updateReturnInfo.put("returnId", returnId);
            updateReturnInfo.put("statusId", "RETURN_RECEIVED");
            updateReturnInfo.put("currentStatusId", "RETURN_REQUESTED");
            updateReturnInfo.put("userLogin", admin);
            Map<String, Object> updateReturnResp = null;
            try {
                updateReturnResp = dispatcher.runSync("updateReturnHeader", updateReturnInfo);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError, 
                        "OrderErrorUnableToUpdateReturnHeaderStatus", locale));
            }

            if (updateReturnResp != null) {
                String errorMessage = ServiceUtil.getErrorMessage(updateReturnResp);
                if (errorMessage != null) {
                    return ServiceUtil.returnError(errorMessage);
                }
            }
        }

        return ServiceUtil.returnSuccess();
    }

    // Private worker methods
    private static boolean validatePin(Delegator delegator, String cardNumber, String pinNumber) {
        GenericValue finAccount = null;
        try {
            finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", cardNumber).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        if (finAccount != null) {
            String dbPin = finAccount.getString("finAccountCode");
            Debug.logInfo("GC Pin Validation: [Sent: " + pinNumber + "] [Actual: " + dbPin + "]", module);
            if (dbPin != null && dbPin.equals(pinNumber)) {
                return true;
            }
        } else {
            Debug.logInfo("GC FinAccount record not found (" + cardNumber + ")", module);
        }
        return false;
    }

    private static String createTransaction(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, 
            BigDecimal amount, String productStoreId, String partyId, String currencyUom, String txType, 
            String finAccountId, Locale locale) throws GeneralException {
        final String coParty = getPayToPartyId(delegator, productStoreId);
        final String paymentMethodType = "GIFT_CERTIFICATE";

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

        String paymentType = null;
        String partyIdFrom = null;
        String partyIdTo = null;
        if ("DEPOSIT".equals(txType)) {
            paymentType = "GC_DEPOSIT";
            partyIdFrom = partyId;
            partyIdTo = coParty;
        } else if ("WITHDRAWAL".equals(txType)) {
            paymentType = "GC_WITHDRAWAL";
            partyIdFrom = coParty;
            partyIdTo = partyId;
        } else {
            throw new GeneralException(UtilProperties.getMessage(resourceError, 
                    "AccountingFinAccountCannotCreateTransaction", locale));
        }

        // 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", amount);
        paymentCtx.put("userLogin", userLogin);
        paymentCtx.put("paymentRefNum", "N/A");

        String paymentId = null;
        Map<String, Object> payResult = null;
        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));
        } else {
            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", userLogin.getString("partyId"));
        transCtx.put("userLogin", userLogin);
        transCtx.put("paymentId", paymentId);
        transCtx.put("amount", amount);

        Map<String, Object> transResult = null;
        String txId = null;
        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));
        } else {
            txId = (String) transResult.get("finAccountTransId");
        }

        return txId;
    }

    private static String generateNumber(Delegator delegator, int length, boolean isId) throws GenericEntityException {
        if (length > 19) {
            length = 19;
        }

        Random rand = new SecureRandom();
        boolean isValid = false;
        StringBuilder number = null;
        while (!isValid) {
            number = new StringBuilder("");
            for (int i = 0; i < length; i++) {
                int randInt = rand.nextInt(9);
                number.append(randInt);
            }

            if (isId) {
                number.append(UtilValidate.getLuhnCheckDigit(number.toString()));

                // validate the number
                if (checkCardNumber(number.toString())) {
                    // make sure this number doens't already exist
                    isValid = checkNumberInDatabase(delegator, number.toString());
                }
            } else {
                isValid = true;
            }
        }
        return number.toString();
    }

    private static boolean checkNumberInDatabase(Delegator delegator, String number) throws GenericEntityException {
        GenericValue finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", number).queryOne();
        if (finAccount == null) {
            return true;
        }
        return false;
    }

    private static boolean checkCardNumber(String number) {
        number = number.replaceAll("\\D", "");
        return UtilValidate.sumIsMod10(UtilValidate.getLuhnSum(number));
    }

    private static String getPayToPartyId(Delegator delegator, String productStoreId) {
        String payToPartyId = "Company"; // default value
        GenericValue productStore = null;
        try {
            productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to locate ProductStore (" + productStoreId + ")", module);
            return null;
        }
        if (productStore != null && productStore.get("payToPartyId") != null) {
            payToPartyId = productStore.getString("payToPartyId");
        }
        return payToPartyId;
    }
}
