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

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.service.ServiceUtil;

import com.ebay.sdk.ApiContext;
import com.ebay.sdk.ApiException;
import com.ebay.sdk.SdkException;
import com.ebay.sdk.SdkSoapException;
import com.ebay.sdk.call.AddDisputeCall;
import com.ebay.sdk.call.AddItemCall;
import com.ebay.sdk.call.AddOrderCall;
import com.ebay.sdk.call.DeleteSellingManagerTemplateCall;
import com.ebay.sdk.call.GetBestOffersCall;
import com.ebay.sdk.call.GetItemCall;
import com.ebay.sdk.call.GetMyeBaySellingCall;
import com.ebay.sdk.call.GetSellingManagerInventoryCall;
import com.ebay.sdk.call.GetSellingManagerSoldListingsCall;
import com.ebay.sdk.call.GetUserCall;
import com.ebay.sdk.call.LeaveFeedbackCall;
import com.ebay.sdk.call.RelistItemCall;
import com.ebay.sdk.call.RespondToBestOfferCall;
import com.ebay.sdk.call.VerifyAddSecondChanceItemCall;
import com.ebay.soap.eBLBaseComponents.AddOrderRequestType;
import com.ebay.soap.eBLBaseComponents.AddOrderResponseType;
import com.ebay.soap.eBLBaseComponents.AmountType;
import com.ebay.soap.eBLBaseComponents.AutomatedLeaveFeedbackEventCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferActionCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferDetailsType;
import com.ebay.soap.eBLBaseComponents.BestOfferStatusCodeType;
import com.ebay.soap.eBLBaseComponents.BestOfferType;
import com.ebay.soap.eBLBaseComponents.BuyerPaymentMethodCodeType;
import com.ebay.soap.eBLBaseComponents.CommentTypeCodeType;
import com.ebay.soap.eBLBaseComponents.CurrencyCodeType;
import com.ebay.soap.eBLBaseComponents.DeleteSellingManagerTemplateRequestType;
import com.ebay.soap.eBLBaseComponents.DeleteSellingManagerTemplateResponseType;
import com.ebay.soap.eBLBaseComponents.DetailLevelCodeType;
import com.ebay.soap.eBLBaseComponents.DisputeExplanationCodeType;
import com.ebay.soap.eBLBaseComponents.DisputeReasonCodeType;
import com.ebay.soap.eBLBaseComponents.FeedbackDetailType;
import com.ebay.soap.eBLBaseComponents.GetSellingManagerInventoryRequestType;
import com.ebay.soap.eBLBaseComponents.GetSellingManagerInventoryResponseType;
import com.ebay.soap.eBLBaseComponents.ItemArrayType;
import com.ebay.soap.eBLBaseComponents.ItemListCustomizationType;
import com.ebay.soap.eBLBaseComponents.ItemSortTypeCodeType;
import com.ebay.soap.eBLBaseComponents.ItemType;
import com.ebay.soap.eBLBaseComponents.ListingTypeCodeType;
import com.ebay.soap.eBLBaseComponents.OrderType;
import com.ebay.soap.eBLBaseComponents.PaginatedItemArrayType;
import com.ebay.soap.eBLBaseComponents.PaginationType;
import com.ebay.soap.eBLBaseComponents.SellingManagerOrderStatusType;
import com.ebay.soap.eBLBaseComponents.SellingManagerPaidStatusCodeType;
import com.ebay.soap.eBLBaseComponents.SellingManagerProductDetailsType;
import com.ebay.soap.eBLBaseComponents.SellingManagerProductType;
import com.ebay.soap.eBLBaseComponents.SellingManagerShippedStatusCodeType;
import com.ebay.soap.eBLBaseComponents.SellingManagerSoldOrderType;
import com.ebay.soap.eBLBaseComponents.SellingManagerSoldTransactionType;
import com.ebay.soap.eBLBaseComponents.SellingManagerTemplateDetailsArrayType;
import com.ebay.soap.eBLBaseComponents.SellingManagerTemplateDetailsType;
import com.ebay.soap.eBLBaseComponents.TradingRoleCodeType;
import com.ebay.soap.eBLBaseComponents.TransactionArrayType;
import com.ebay.soap.eBLBaseComponents.TransactionType;
import com.ebay.soap.eBLBaseComponents.UserType;

public class EbayStoreAutoPreferences {
    public static String MODULE = EbayStoreAutoPreferences.class.getName();
    private static final String RESOURCE = "EbayStoreUiLabels";

    public EbayStoreAutoPreferences() {

    }

    /*  It may take several minutes to process your automated feedback.  to connect to ebay site*/
    public static Map<String, Object> autoPrefLeaveFeedbackOption(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {

        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");

        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreRequiredProductStoreId", locale));
        }
        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");
        String isAutoPositiveFeedback = "N";
        String feedbackEventCode = null;
        GenericValue ebayProductStorePref = null;
        List<String> list = new LinkedList<>();

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB").queryOne();
            if (ebayProductStorePref != null && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoPositiveFeedback = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoPositiveFeedback) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    feedbackEventCode = ebayProductStorePref.getString("condition1");
                    String storeComments = ebayProductStorePref.getString("condition2");
                    String comment = null;
                    if (UtilValidate.isNotEmpty(storeComments)) {
                        if (storeComments.indexOf("\\[,\\]") != -1) {
                            String[] strs = storeComments.split("\\[,\\]");
                            for (String str : strs) {
                                list.add(str);
                            }
                        }
                    }
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);

                    List<SellingManagerSoldOrderType> items = new LinkedList<SellingManagerSoldOrderType>();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null && !orderStatus.isFeedbackSent()) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                CommentTypeCodeType commentType = orderStatus.getFeedbackReceived();
                                //Buyer has paid for this item.
                                if ("PAYMENT_RECEIVED".equals(feedbackEventCode) && SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                                //Buyer has paid for this item and left me positive feedback.
                                if ("POSITIVE_FEEDBACK_RECEIVED".equals(feedbackEventCode) && CommentTypeCodeType.POSITIVE.equals(commentType) && SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                            }
                        }
                        GetUserCall getUserCall = new GetUserCall(apiContext);
                        String commentingUser = getUserCall.getUser().getUserID();
                        for (SellingManagerSoldOrderType item : items) {
                            // start leave feedbacks
                            SellingManagerSoldTransactionType[] soldTrans = item.getSellingManagerSoldTransaction();
                            if (UtilValidate.isNotEmpty(soldTrans)) {
                                for (SellingManagerSoldTransactionType soldTran : soldTrans) {
                                    LeaveFeedbackCall leaveFeedbackCall = new LeaveFeedbackCall(apiContext);
                                    FeedbackDetailType detail = new FeedbackDetailType();
                                    // ramdom comments
                                    if (!list.isEmpty()) {
                                        Collections.shuffle(list, new Random());
                                        comment = list.get(0);
                                    }
                                    detail.setCommentText(comment);
                                    detail.setCommentingUser(commentingUser);
                                    //detail.setCommentingUserScore(value);
                                    detail.setCommentType(CommentTypeCodeType.POSITIVE);
                                    detail.setItemID(soldTran.getItemID());
                                    detail.setItemPrice(soldTran.getItemPrice());
                                    detail.setItemTitle(soldTran.getItemTitle());
                                    leaveFeedbackCall.setFeedbackDetail(detail);
                                    leaveFeedbackCall.setTargetUser(item.getBuyerID());
                                    leaveFeedbackCall.setTransactionID(String.valueOf(soldTran.getTransactionID()));
                                    leaveFeedbackCall.leaveFeedback();
                                    Debug.logInfo("Auto leave feedback with site ".concat(apiContext.getSite().value()).concat("itemId ".concat(soldTran.getItemID())).concat(" comment is ".concat(comment)), MODULE);
                                }
                            }
                        }
                    }
                }
            }
        } catch (GenericEntityException gee) {
            return ServiceUtil.returnError(gee.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }

    public static String autoPrefLeaveFeedbackOptions(HttpServletRequest request, HttpServletResponse response) {
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        Locale locale = UtilHttp.getLocale(request);
        Map<String, Object> paramMap = UtilHttp.getCombinedMap(request);

        if (UtilValidate.isEmpty(paramMap.get("productStoreId"))) {
            request.setAttribute("_ERROR_MESSAGE_", "Required productStoreId for get api context to connect with ebay site.");
            return "error";
        }

        String productStoreId = (String) paramMap.get("productStoreId");
        String isAutoPositiveFeedback = "N";
        String condition = null;
        if (UtilValidate.isNotEmpty(paramMap.get("isAutoPositiveFeedback"))) {
            isAutoPositiveFeedback = (String) paramMap.get("isAutoPositiveFeedback");
        }
        String feedbackEventCode = (String) paramMap.get("feedbackEventCode");
        ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);

        try {
            Map<String, Object> resultMap = new HashMap<>();
            GenericValue ebayProductStorePref = null;
            String comments = null;
            String autoPrefJobId = null;
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            if ("Y".equals(isAutoPositiveFeedback)) {
                if ("PAYMENT_RECEIVED".equals(feedbackEventCode)) {
                    condition = AutomatedLeaveFeedbackEventCodeType.PAYMENT_RECEIVED.toString();
                } else if ("POSITIVE_FEEDBACK_RECEIVED".equals(feedbackEventCode)) {
                    condition = AutomatedLeaveFeedbackEventCodeType.POSITIVE_FEEDBACK_RECEIVED.toString();
                }
                // allow only 10 comment can be store / set new comments to condition2 separate by [,]
            }
            for (int i = 1; i <= 5; i++) {
                String comment = (String) paramMap.get("comment_".concat(String.valueOf(i)));
                if (comment != null && !comment.isEmpty()) {
                    if (comments == null) {
                        comments = comment;
                    } else {
                        comments = comments.concat("[").concat(",").concat(("]").concat(comment));
                    }
                }
            }
            if (UtilValidate.isEmpty(comments)) {
                request.setAttribute("_ERROR_MESSAGE_", "Required least one at comment for your store feedback send with ebay site.");
                return "error";
            }

            Map<String, Object> context = UtilMisc.<String, Object>toMap("userLogin", userLogin, "serviceName", "autoPrefLeaveFeedbackOption");
            ebayProductStorePref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_PIT_FB").queryOne();
            context.put("productStoreId", productStoreId);
            context.put("autoPrefEnumId", "EBAY_AUTO_PIT_FB");
            if (ebayProductStorePref != null && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                autoPrefJobId = ebayProductStorePref.getString("autoPrefJobId");
            }
            context.put("autoPrefJobId", autoPrefJobId);
            context.put("enabled", isAutoPositiveFeedback);
            context.put("condition1", condition);
            context.put("condition2", comments);
            context.put("condition3", null);
            if (UtilValidate.isEmpty(ebayProductStorePref)) {
                resultMap = dispatcher.runSync("createEbayProductStorePref", context);
                if (ServiceUtil.isError(resultMap)) {
                    String errorMessage = ServiceUtil.getErrorMessage(resultMap);
                    request.setAttribute("_ERROR_MESSAGE_", errorMessage);
                    Debug.logError(errorMessage, MODULE);
                    return "error";
                }
            } else {
                resultMap = dispatcher.runSync("updateEbayProductStorePref", context);
                if (ServiceUtil.isError(resultMap)) {
                    String errorMessage = ServiceUtil.getErrorMessage(resultMap);
                    request.setAttribute("_ERROR_MESSAGE_", errorMessage);
                    Debug.logError(errorMessage, MODULE);
                    return "error";
                }
            }
            request.setAttribute("_EVENT_MESSAGE_", "Setting Automated Positive Feedback for Buyers Success with site " + apiContext.getSite().value());

        } catch (GenericEntityException | GenericServiceException e) {
            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
            return "error";
        }

        return "success";
    }

    /* start automatically service send a Feedback Reminder email if feedback has not been received. and check how many days after shipping you want this email sent? */
    public static Map<String, Object> autoSendFeedbackReminderEmail(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreRequiredProductStoreId", locale));
        }
        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");
        String isAutoFeedbackReminder = "N";
        int afterDays = 0;
        GenericValue ebayProductStorePref = null;
        String dateTimeFormat = UtilDateTime.getDateTimeFormat();
        SimpleDateFormat formatter = new SimpleDateFormat(dateTimeFormat);

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD").queryOne();
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoFeedbackReminder = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoFeedbackReminder) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    afterDays = Integer.parseInt(ebayProductStorePref.getString("condition1"));
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
                    List<SellingManagerSoldOrderType> items = new LinkedList<SellingManagerSoldOrderType>();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                SellingManagerShippedStatusCodeType shippedStatus = orderStatus.getShippedStatus();

                                //Buyer has paid for this item.  && Seller shipped items but feedback has not been received from buyer more than days condition
                                if (SellingManagerPaidStatusCodeType.PAID.equals(paidStatus) && SellingManagerShippedStatusCodeType.SHIPPED.equals(shippedStatus)) {
                                    Calendar right_now = Calendar.getInstance();
                                    Calendar shippedTime = orderStatus.getShippedTime();
                                    Calendar afterShippedTime = orderStatus.getShippedTime();
                                    afterShippedTime.add(Calendar.DAY_OF_MONTH, afterDays);
                                    Debug.logInfo("Verify date for send reminder feedback eamil by auto service: buyer " + solditem.getBuyerID() + " seller shippedTime "
                                            + "" + formatter.format(shippedTime) + " codition days " + afterDays + " after shippedTime :" + formatter.format(afterShippedTime) + " now date" + formatter.format(right_now), MODULE);
                                    // if now date is after shipped time follow after days condition would be send reminder email to buyer
                                    if (right_now.after(afterShippedTime)) {
                                        items.add(solditem);
                                    }
                                }
                            }
                        }

                        // call service send email (get template follow productStoreId)
                        for (SellingManagerSoldOrderType item : items) {
                            // call send
                            Map<String, Object> sendMap = new HashMap<>();
                            GenericValue productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_FEEBACK_REMIN").queryOne();
                            String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                            sendMap.put("bodyScreenUri", bodyScreenLocation);
                            String subjectString = productStoreEmail.getString("subject");
                            sendMap.put("userLogin", userLogin);
                            sendMap.put("subject", subjectString);
                            sendMap.put("contentType", productStoreEmail.get("contentType"));
                            sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                            sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                            sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                            sendMap.put("sendTo", item.getBuyerEmail());

                            Map<String, Object> bodyParameters = new HashMap<>();
                            bodyParameters.put("buyerUserId", item.getBuyerID());
                            sendMap.put("bodyParameters", bodyParameters);

                            try {
                                dispatcher.runAsync("sendMailFromScreen", sendMap);
                            } catch (GenericServiceException e) {
                                Debug.logError(e, MODULE);
                                return ServiceUtil.returnError(e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayRelistSoldItems(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            Map<String, Object> serviceMap = new HashMap<>();
            serviceMap.put("userLogin", userLogin);
            //ProductStore
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            if (!productStores.isEmpty()) {
                // get auto preference setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                // convert preference setting
                Timestamp fromDate = UtilDateTime.toTimestamp(condition1);
                Timestamp thruDate = UtilDateTime.toTimestamp(condition2);
                Timestamp nowTime = UtilDateTime.nowTimestamp();
                if (nowTime.after(fromDate) && nowTime.before(thruDate)) {
                    serviceMap.put("productStoreId", productStoreId);
                    Map<String, Object> eBayUserLogin = dispatcher.runSync("getEbayStoreUser", serviceMap);
                    if (ServiceUtil.isError(eBayUserLogin)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(eBayUserLogin));
                    }
                    String eBayUserLoginId = (String) eBayUserLogin.get("userLoginId");
                    GenericValue party = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", eBayUserLoginId).queryOne();
                    String partyId = party.getString("partyId");
                    //save sold items to OFbBiz product entity
                    Map<String, Object> serviceResult = dispatcher.runSync("getEbaySoldItems", serviceMap);
                    if (ServiceUtil.isError(resultService)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultService));
                    }
                    List<Map<String, Object>> soldItems = UtilGenerics.checkList(serviceResult.get("soldItems"));
                    if (!soldItems.isEmpty()) {
                        for (Map<String, Object> soldItemMap : soldItems) {
                            if (UtilValidate.isNotEmpty(soldItemMap.get("itemId"))) {
                                GenericValue productCheck = EntityQuery.use(delegator).from("Product").where("productId", soldItemMap.get("itemId")).queryOne();
                                if (productCheck == null) {
                                    Map<String, Object> inMap = new HashMap<>();
                                    inMap.put("productId", soldItemMap.get("itemId"));
                                    inMap.put("productTypeId", "EBAY_ITEM");
                                    inMap.put("internalName", "eBay Item " + soldItemMap.get("title"));
                                    inMap.put("userLogin", userLogin);
                                    Map<String, Object> result = dispatcher.runSync("createProduct", inMap);
                                    if (ServiceUtil.isError(result)) {
                                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
                                    }
                                    // ProductRole (VENDOR)
                                    List<GenericValue> productRole = EntityQuery.use(delegator).from("ProductRole").where("partyId", partyId, "productId", soldItemMap.get("itemId"), "roleTypeId", "VENDOR").queryList();
                                    if (productRole.isEmpty()) {
                                        Map<String, Object> addRole = new HashMap<>();
                                        addRole.put("productId", soldItemMap.get("itemId"));
                                        addRole.put("roleTypeId", "VENDOR");
                                        addRole.put("partyId", partyId);
                                        addRole.put("fromDate", UtilDateTime.nowTimestamp());
                                        addRole.put("userLogin", userLogin);
                                        Map<String, Object> result = dispatcher.runSync("addPartyToProduct", addRole);
                                        if (ServiceUtil.isError(result)) {
                                            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    //check active items
                    serviceMap = new HashMap<>();
                    serviceMap.put("userLogin", userLogin);
                    serviceMap.put("productStoreId", productStoreId);
                    serviceResult = dispatcher.runSync("getEbayActiveItems", serviceMap);
                    if (ServiceUtil.isError(resultService)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultService));
                    }
                    List<Map<String, Object>> activeItems = UtilGenerics.checkList(serviceResult.get("activeItems"));
                    List<String> activeItemMaps = new LinkedList<>();
                    if (!activeItems.isEmpty()) {
                        for (Map<String, Object> activeItem : activeItems) {
                            Map<String, Object> activeItemMap = UtilGenerics.checkMap(activeItem);
                            if (UtilValidate.isNotEmpty(activeItemMap.get("itemId"))) {
                                activeItemMaps.add((String) activeItemMap.get("itemId"));
                            }
                        }
                    }
                    //check product role
                    List<GenericValue> productRoles = EntityQuery.use(delegator).from("ProductRole").where("partyId", partyId, "roleTypeId", "VENDOR").queryList();
                    List<String> productRoleIds = new LinkedList<>();
                    if (!productRoles.isEmpty()) {
                        for (GenericValue productRole : productRoles) {
                            String productId = productRole.getString("productId");
                            productRoleIds.add(productId);
                        }
                    }
                    List<EntityCondition> andExpr = new LinkedList<>();
                    EntityCondition activeItemCond = EntityCondition.makeCondition("productId", EntityOperator.NOT_IN, activeItemMaps);
                    andExpr.add(activeItemCond);
                    EntityCondition productTypeCond = EntityCondition.makeCondition("productTypeId", EntityOperator.EQUALS, "EBAY_ITEM");
                    andExpr.add(productTypeCond);
                    EntityCondition isVirtualCond = EntityCondition.makeCondition("isVirtual", EntityOperator.NOT_EQUAL, "Y");
                    andExpr.add(isVirtualCond);
                    EntityCondition productRole = EntityCondition.makeCondition("productId", EntityOperator.IN, productRoleIds);
                    andExpr.add(productRole);
                    List<GenericValue> itemsToRelist = EntityQuery.use(delegator).from("Product").where(andExpr).queryList();
                    if (!itemsToRelist.isEmpty()) {
                        //re-list sold items and not active
                        ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                        for (GenericValue genericValue : itemsToRelist) {
                            RelistItemCall relistItemCall = new RelistItemCall(apiContext);
                            ItemType itemToBeRelisted = new ItemType();
                            GenericValue product = genericValue;
                            itemToBeRelisted.setItemID(product.getString("productId"));
                            relistItemCall.setItemToBeRelisted(itemToBeRelisted);
                            relistItemCall.relistItem();
                            GenericValue productStore = EntityQuery.use(delegator).from("Product").where("productId", product.getString("productId")).queryOne();
                            productStore.set("isVirtual", "Y");
                            productStore.store();
                            Debug.logInfo("Relisted Item - " + product.getString("productId"), MODULE);
                        }
                    }
                }
            }
        } catch (GenericEntityException | GenericServiceException ge) {
            return ServiceUtil.returnError(ge.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayDisputeNotComplete(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            if (!productStores.isEmpty()) {
                // get automatic setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                String condition3 = productStores.get(0).getString("condition3");
                // convert automatic setting for usage
                int afterDays = 0;
                if (UtilValidate.isInteger(condition1)) {
                    afterDays = Integer.parseInt(condition1);
                }
                DisputeReasonCodeType disputeReason = null;
                if (UtilValidate.isNotEmpty(condition2)) {
                    disputeReason = DisputeReasonCodeType.valueOf(condition2);
                }
                DisputeExplanationCodeType disputeExplanation = null;
                if (UtilValidate.isNotEmpty(condition3)) {
                    disputeExplanation = DisputeExplanationCodeType.valueOf(condition3);
                }
                // get sold items
                Map<String, Object> serviceMap = new HashMap<>();
                serviceMap.put("productStoreId", productStoreId);
                serviceMap.put("userLogin", userLogin);
                Map<String, Object> serviceResult = dispatcher.runSync("getEbaySoldItems", serviceMap);
                if (ServiceUtil.isError(resultService)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultService));
                }
                List<Map<String, Object>> soldItems = UtilGenerics.checkList(serviceResult.get("soldItems"));
                // check items to dispute
                List<Map<String, Object>> itemsToDispute = new LinkedList<>();
                for (Map<String, Object> soldItem : soldItems) {
                    Map<String, Object> item = UtilGenerics.checkMap(soldItem);
                    String checkoutStatus = (String) item.get("checkoutStatus");
                    Date creationTime = (Date) item.get("creationTime");
                    Date paidTime = (Date) item.get("paidTime");
                    String unpaidItemStatus = (String) item.get("unpaidItemStatus");
                    int checkDays = UtilDateTime.getIntervalInDays(UtilDateTime.toTimestamp(creationTime), UtilDateTime.nowTimestamp());
                    if (checkDays > afterDays && "CheckoutIncomplete".equals(checkoutStatus) && unpaidItemStatus == null && paidTime == null && "CheckoutComplete" != checkoutStatus) {
                        itemsToDispute.add(item);
                    }
                }
                // Dispute items
                if (disputeReason != null && disputeExplanation != null && !itemsToDispute.isEmpty()) {
                    ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                    DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[]{
                            DetailLevelCodeType.RETURN_ALL,
                            DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                            DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
                    };
                    for (Map<String, Object> item : itemsToDispute) {
                        AddDisputeCall api = new AddDisputeCall(apiContext);
                        api.setDetailLevel(detailLevels);
                        api.setItemID((String) item.get("itemId"));
                        api.setTransactionID((String) item.get("transactionId"));
                        api.setDisputeExplanation(disputeExplanation);
                        api.setDisputeReason(disputeReason);
                    }
                }
            }
        } catch (GenericEntityException | GenericServiceException ge) {
            return ServiceUtil.returnError(ge.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> automaticEbayDisputeNotPay(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String jobId = (String) context.get("jobId");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            List<GenericValue> productStores = EntityQuery.use(delegator).from("EbayProductStorePref").where("autoPrefJobId", jobId).queryList();
            if (!productStores.isEmpty()) {
                // get automatic setting
                String productStoreId = productStores.get(0).getString("productStoreId");
                String condition1 = productStores.get(0).getString("condition1");
                String condition2 = productStores.get(0).getString("condition2");
                String condition3 = productStores.get(0).getString("condition3");
                // convert automatic setting for usage
                int afterDays = 0;
                if (UtilValidate.isInteger(condition1)) {
                    afterDays = Integer.parseInt(condition1);
                }
                DisputeReasonCodeType disputeReason = null;
                if (UtilValidate.isNotEmpty(condition2)) {
                    disputeReason = DisputeReasonCodeType.valueOf(condition2);
                }
                DisputeExplanationCodeType disputeExplanation = null;
                if (UtilValidate.isNotEmpty(condition3)) {
                    disputeExplanation = DisputeExplanationCodeType.valueOf(condition3);
                }
                // get sold items
                Map<String, Object> serviceMap = new HashMap<>();
                serviceMap.put("productStoreId", productStoreId);
                serviceMap.put("userLogin", userLogin);
                Map<String, Object> serviceResult = dispatcher.runSync("getEbaySoldItems", serviceMap);
                if (ServiceUtil.isError(resultService)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultService));
                }
                List<Map<String, Object>> soldItems = UtilGenerics.checkList(serviceResult.get("soldItems"));
                // check items to dispute
                List<Map<String, Object>> itemsToDispute = new LinkedList<>();
                for (Map<String, Object> soldItem : soldItems) {
                    Map<String, Object> item = UtilGenerics.checkMap(soldItem);
                    String checkoutStatus = (String) item.get("checkoutStatus");
                    Date creationTime = (Date) item.get("creationTime");
                    Date paidTime = (Date) item.get("paidTime");
                    String unpaidItemStatus = (String) item.get("unpaidItemStatus");
                    int checkDays = UtilDateTime.getIntervalInDays(UtilDateTime.toTimestamp(creationTime), UtilDateTime.nowTimestamp());
                    if (checkDays > afterDays && unpaidItemStatus == null && paidTime == null && "CheckoutComplete" == checkoutStatus) {
                        itemsToDispute.add(item);
                    }
                }
                // Dispute items
                if (disputeReason != null && disputeExplanation != null && !itemsToDispute.isEmpty()) {
                    ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
                    DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[]{
                            DetailLevelCodeType.RETURN_ALL,
                            DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                            DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
                    };
                    for (Map<String, Object> item : itemsToDispute) {
                        AddDisputeCall api = new AddDisputeCall(apiContext);
                        api.setDetailLevel(detailLevels);
                        api.setItemID((String) item.get("itemId"));
                        api.setTransactionID((String) item.get("transactionId"));
                        api.setDisputeExplanation(disputeExplanation);
                        api.setDisputeReason(disputeReason);
                    }
                }
            }
        } catch (GenericEntityException | GenericServiceException ge) {
            return ServiceUtil.returnError(ge.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    /* start automatically service send an email when ebay seller has been received payment from ebay buyer */
    public static Map<String, Object> autoSendPaymentReceivedEmail(DispatchContext dctx, Map<String, ? extends Object> context) throws ApiException, SdkException, Exception {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();

        if (UtilValidate.isEmpty(context.get("productStoreId")) && UtilValidate.isEmpty(context.get("jobId"))) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreRequiredProductStoreId", locale));
        }

        String jobId = (String) context.get("jobId");
        String productStoreId = (String) context.get("productStoreId");

        String isAutoSendEmail = "N";
        GenericValue ebayProductStorePref = null;

        try {
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            ebayProductStorePref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_FB_RMD").queryOne();
            if (UtilValidate.isNotEmpty(ebayProductStorePref) && UtilValidate.isNotEmpty(ebayProductStorePref.getString("autoPrefJobId"))) {
                isAutoSendEmail = ebayProductStorePref.getString("enabled");
                // if isAutoPositiveFeedback is N that means not start this job run service
                if ("Y".equals(isAutoSendEmail) && jobId.equals(ebayProductStorePref.getString("autoPrefJobId"))) {
                    // start getting sold item list from ebay follow your site
                    GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
                    List<SellingManagerSoldOrderType> items = new LinkedList<SellingManagerSoldOrderType>();
                    SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
                    if (UtilValidate.isNotEmpty(sellingManagerSoldOrders)) {
                        for (SellingManagerSoldOrderType solditem : sellingManagerSoldOrders) {
                            SellingManagerOrderStatusType orderStatus = solditem.getOrderStatus();
                            if (orderStatus != null) {
                                SellingManagerPaidStatusCodeType paidStatus = orderStatus.getPaidStatus();
                                //Buyer has paid for this item. and seller received
                                if (SellingManagerPaidStatusCodeType.PAID.equals(paidStatus)) {
                                    items.add(solditem);
                                }
                            }
                        }

                        // call service send email (get template follow productStoreId)
                        for (SellingManagerSoldOrderType item : items) {
                            // call send
                            Map<String, Object> sendMap = new HashMap<>();
                            GenericValue productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_PAY_RECIEVED").queryOne();
                            String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                            sendMap.put("bodyScreenUri", bodyScreenLocation);
                            String subjectString = productStoreEmail.getString("subject");
                            sendMap.put("userLogin", userLogin);
                            sendMap.put("subject", subjectString);
                            sendMap.put("contentType", productStoreEmail.get("contentType"));
                            sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                            sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                            sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                            sendMap.put("sendTo", item.getBuyerEmail());

                            Map<String, Object> bodyParameters = new HashMap<>();
                            bodyParameters.put("buyerUserId", item.getBuyerID());
                            sendMap.put("bodyParameters", bodyParameters);

                            try {
                                dispatcher.runAsync("sendMailFromScreen", sendMap);
                            } catch (GenericServiceException e) {
                                Debug.logError(e, MODULE);
                                return ServiceUtil.returnError(e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreProblemConnectingToEbaySite", locale) + e);
        }

        return ServiceUtil.returnSuccess();
    }


    public static Map<String, Object> runCombineOrders(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = new HashMap<>();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String productStoreId = (String) context.get("productStoreId");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            GetSellingManagerSoldListingsCall sellingManagerSoldListings = new GetSellingManagerSoldListingsCall(apiContext);
            SellingManagerSoldOrderType[] sellingManagerSoldOrders = sellingManagerSoldListings.getSellingManagerSoldListings();
            if (sellingManagerSoldOrders != null) {
                int soldOrderLength = sellingManagerSoldOrders.length;
                GenericValue ebayPref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "ENA_COMB_ORD").queryOne();
                if (ebayPref != null) {

                    Timestamp beginDate = UtilDateTime.toTimestamp("01/01/2001 00:00:00");
                    Long daysCount = Long.parseLong(ebayPref.get("condition1").toString());
                    Hashtable<String, List<Map<String, Object>>> h = new Hashtable<>();

                    for (SellingManagerSoldOrderType sellingManagerSoldOrder : sellingManagerSoldOrders) {
                        String buyerId = sellingManagerSoldOrder.getBuyerID().toString();
                        List<Map<String, Object>> soldGroupList = new LinkedList<>();
                        Map<String, Object> mymap = new HashMap<>();
                        mymap.put("group", "");
                        mymap.put("soldorder", sellingManagerSoldOrder);
                        if (!h.isEmpty()) {
                            Enumeration<String> enums = h.keys();
                            String key = "";
                            while (enums.hasMoreElements()) {
                                key = enums.nextElement();
                                List<Map<String, Object>> tempList = h.get(key);
                                if (key.equals(buyerId)) {
                                    key = buyerId;
                                    tempList.add(mymap);
                                    h.put(buyerId, tempList);
                                }
                            }
                            if (!key.equals(buyerId)) {
                                soldGroupList.clear();
                                soldGroupList.add(mymap);
                                h.put(buyerId, soldGroupList);
                            }
                        } else {
                            soldGroupList.add(mymap);
                            h.put(buyerId, soldGroupList);
                        }
                    }

                    Enumeration<String> enums = h.keys();
                    while (enums.hasMoreElements()) {
                        int groupRunning = 0;
                        String key = enums.nextElement();
                        List<Map<String, Object>> soldGroupList = h.get(key);
                        int maxItems = Integer.parseInt(ebayPref.get("condition2").toString());

                        if (soldGroupList.size() > 1) {
                            for (int j = 0; j < soldGroupList.size(); j++) {
                                Map<String, Object> myMap = soldGroupList.get(j);
                                SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) myMap.get("soldorder");
                                Timestamp createdate = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
                                if (myMap.get("group").toString().isEmpty()) {
                                    beginDate = createdate;
                                }
                                beginDate = findStartDate(beginDate, soldGroupList);
                                runCheckAndGroup(groupRunning, beginDate, daysCount, soldGroupList);
                                groupRunning++;
                            }

                            int x = 0;
                            while (x < groupRunning) {
                                OrderType order = new OrderType();
                                order.setCreatingUserRole(TradingRoleCodeType.SELLER);
                                BuyerPaymentMethodCodeType[] buyerPayment = new BuyerPaymentMethodCodeType[1];
                                buyerPayment[0] = BuyerPaymentMethodCodeType.CASH_ON_PICKUP;
                                order.setPaymentMethods(buyerPayment);
                                TransactionArrayType transactionArr = new TransactionArrayType();
                                List<TransactionType> translist = new LinkedList<TransactionType>();

                                AmountType total = new AmountType();
                                double totalAmt = 0.0;
                                CurrencyCodeType currencyId = null;
                                int totalQty = 0;

                                for (Map<String, Object> myMap : soldGroupList) {
                                    if (UtilValidate.isNotEmpty(myMap.get("group"))) {
                                        if (x == Integer.parseInt(myMap.get("group").toString())) {
                                            SellingManagerSoldOrderType sellingManagerSoldOrder = (SellingManagerSoldOrderType) myMap.get("soldorder");
                                            String buyerId = sellingManagerSoldOrder.getBuyerID().toString();
                                            int qty = sellingManagerSoldOrder.getTotalQuantity();
                                            totalQty = totalQty + qty;
                                            if (key.equals(buyerId) && (UtilValidate.isEmpty(sellingManagerSoldOrder.getOrderStatus().getPaidTime()))) {
                                                double totalAmount = 0.0;
                                                if (UtilValidate.isNotEmpty(sellingManagerSoldOrder.getTotalAmount())) {
                                                    totalAmount = sellingManagerSoldOrder.getTotalAmount().getValue();
                                                    currencyId = sellingManagerSoldOrder.getTotalAmount().getCurrencyID();
                                                } else {
                                                    totalAmount = sellingManagerSoldOrder.getSalePrice().getValue();
                                                    currencyId = sellingManagerSoldOrder.getSalePrice().getCurrencyID();
                                                }
                                                //Combine
                                                totalAmt = totalAmt + totalAmount;
                                                SellingManagerSoldTransactionType[] sellingManagerSoldTransactions = sellingManagerSoldOrder.getSellingManagerSoldTransaction();
                                                //set transaction
                                                for (SellingManagerSoldTransactionType sellingManagerSoldTransaction : sellingManagerSoldTransactions) {
                                                    TransactionType transtype = new TransactionType();
                                                    ItemType itemtype = new ItemType();
                                                    if (UtilValidate.isNotEmpty(sellingManagerSoldTransaction.getItemID())) {
                                                        itemtype.setItemID(sellingManagerSoldTransaction.getItemID());
                                                        transtype.setItem(itemtype);
                                                        transtype.setTransactionID(sellingManagerSoldTransaction.getTransactionID().toString());
                                                        translist.add(transtype);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                if (totalQty < maxItems) {
                                    total.setValue(totalAmt);
                                    total.setCurrencyID(currencyId);
                                    TransactionType[] transArr = new TransactionType[translist.size()];
                                    for (int counter = 0; counter < translist.size(); counter++) {
                                        transArr[counter] = translist.get(counter);
                                    }
                                    transactionArr.setTransaction(transArr);
                                    if (transactionArr.getTransactionLength() > 1) {
                                        order.setTotal(total);
                                        order.setTransactionArray(transactionArr);
                                        AddOrderCall call = new AddOrderCall(apiContext);
                                        AddOrderRequestType req = new AddOrderRequestType();
                                        AddOrderResponseType resp = null;
                                        req.setOrder(order);
                                        resp = (AddOrderResponseType) call.execute(req);
                                        if (resp != null && "SUCCESS".equals(resp.getAck().toString())) {
                                            String orderId = resp.getOrderID();
                                            Debug.logInfo(":: new order id is = " + orderId, MODULE);
                                        } else {
                                            EbayStoreHelper.createErrorLogMessage(userLogin, dispatcher, productStoreId, resp.getAck().toString(), "Add order : runCombineOrders", resp.getErrors(0).getLongMessage());
                                        }
                                    }
                                }
                                x++;
                            }
                        }
                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericEntityException | GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Timestamp findStartDate(Timestamp lessStartTimestamp, List<Map<String, Object>> inList) {
        for (Map<String, Object> inMap : inList) {
            SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) inMap.get("soldorder");
            Timestamp createTimestamp = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
            String group = (String) inMap.get("group");
            if (createTimestamp.before(lessStartTimestamp) && group.isEmpty()) {
                lessStartTimestamp = createTimestamp;
            }
        }
        return lessStartTimestamp;
    }

    public static void runCheckAndGroup(int groupRunning, Timestamp startTimestamp, long countDays, List<Map<String, Object>> inList) {
        Timestamp endDate = UtilDateTime.getDayEnd(UtilDateTime.toTimestamp(startTimestamp), countDays);
        for (Map<String, Object> inMap : inList) {
            String group = inMap.get("group").toString();
            SellingManagerSoldOrderType soldorder = (SellingManagerSoldOrderType) inMap.get("soldorder");
            if (group.isEmpty()) {
                Timestamp createtimestamp = UtilDateTime.toTimestamp(soldorder.getCreationTime().getTime());
                if (((createtimestamp.equals(startTimestamp)) || (createtimestamp.after(startTimestamp))) && (createtimestamp.before(endDate))) {
                    inMap.put("group", "" + groupRunning);
                }
            }
        }
    }

    public static Map<String, Object> autoSendWinningBuyerNotification(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = new HashMap<>();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String productStoreId = (String) context.get("productStoreId");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            Map<String, Object> resultSold = dispatcher.runSync("getEbaySoldItems", UtilMisc.toMap("productStoreId", productStoreId, "userLogin", userLogin));
            if (ServiceUtil.isError(resultSold)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultSold));
            }
            List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultSold.get("soldItems"));
            if (!soldItems.isEmpty()) {
                for (Map<String, Object> item : soldItems) {
                    Timestamp lastestTime = UtilDateTime.getDayStart(UtilDateTime.nowTimestamp(), 1);
                    Date creationDate = (Date) item.get("creationTime");
                    Timestamp creationTime = UtilDateTime.toTimestamp(creationDate);

                    if (creationTime.equals(lastestTime) && ("Chinese".equals(item.get("listingType").toString()))) {
                        Map<String, Object> serviceMap = new HashMap<>();
                        serviceMap.put("userLogin", userLogin);
                        serviceMap.put("locale", locale);
                        serviceMap.put("productStoreId", productStoreId);
                        serviceMap.put("itemId", item.get("itemId").toString());
                        Map<String, Object> resultBid = dispatcher.runSync("getEbayAllBidders", serviceMap);
                        if (ServiceUtil.isError(resultBid)) {
                            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultBid));
                        }
                        List<Map<String, Object>> allBidders = UtilGenerics.checkList(resultBid.get("allBidders"));

                        if (!allBidders.isEmpty()) {
                            // call to send email to bidder
                            for (Map<String, Object> bidder : allBidders) {
                                UserType user = (UserType) bidder.get("bidder");
                                String buyerUserId = bidder.get("userId").toString();

                                Map<String, Object> sendMap = new HashMap<>();
                                GenericValue productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_WIN_BUYER_NOTI").queryOne();
                                String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                                sendMap.put("bodyScreenUri", bodyScreenLocation);
                                String subjectString = productStoreEmail.getString("subject");
                                sendMap.put("userLogin", userLogin);
                                sendMap.put("subject", subjectString);
                                sendMap.put("contentType", productStoreEmail.get("contentType"));
                                sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                                sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                                sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                                sendMap.put("sendTo", user.getEmail());

                                Map<String, Object> bodyParameters = new HashMap<>();
                                bodyParameters.put("buyerUserId", buyerUserId);
                                sendMap.put("bodyParameters", bodyParameters);

                                try {
                                    dispatcher.runAsync("sendMailFromScreen", sendMap);
                                } catch (GenericServiceException e) {
                                    Debug.logError(e, MODULE);
                                    return ServiceUtil.returnError(e.getMessage());
                                }
                            }
                        }
                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Map<String, Object> autoSendItemDispatchedNotification(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = new HashMap<>();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        String productStoreId = (String) context.get("productStoreId");

        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            context.put("userLogin", userLogin);
            Map<String, Object> resultSold = dispatcher.runSync("getEbaySoldItems", context);
            if (ServiceUtil.isError(resultSold)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(resultSold));
            }
            List<Map<String, Object>> soldItems = UtilGenerics.checkList(resultSold.get("soldItems"));
            if (!soldItems.isEmpty()) {
                for (Map<String, Object> item : soldItems) {
                    String shippedStatus = item.get("shippedStatus").toString();
                    Timestamp lastestTime = UtilDateTime.getDayStart(UtilDateTime.nowTimestamp(), 1);
                    Date shippedTime = (Date) item.get("shippedTime");
                    Timestamp shippedTimestamp = UtilDateTime.toTimestamp(shippedTime);

                    if ("SHIPPED".equals(shippedStatus) && shippedTimestamp.equals(lastestTime)) {
                        String buyerUserId = item.get("buyerUserId").toString();
                        String buyerEmail = item.get("buyerEmail").toString();

                         Map<String, Object> sendMap = new HashMap<>();
                         GenericValue productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "EBAY_ITEM_DISPATCH").queryOne();
                         String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
                         sendMap.put("bodyScreenUri", bodyScreenLocation);
                         String subjectString = productStoreEmail.getString("subject");
                         sendMap.put("userLogin", userLogin);
                         sendMap.put("subject", subjectString);
                         sendMap.put("contentType", productStoreEmail.get("contentType"));
                         sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
                         sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
                         sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
                         sendMap.put("sendTo", buyerEmail);

                         Map<String, Object> bodyParameters = new HashMap<>();
                         bodyParameters.put("buyerUserId", buyerUserId);
                         sendMap.put("bodyParameters", bodyParameters);

                         try {
                             dispatcher.runAsync("sendMailFromScreen", sendMap);
                         } catch (Exception e) {
                             Debug.logError(e, MODULE);
                             return ServiceUtil.returnError(e.getMessage());
                         }

                    }
                }
            }
            result = ServiceUtil.returnSuccess();
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return result;
    }

    public static Map<String, Object> autoBlockItemsOutOfStock(DispatchContext dctx, Map<String, Object> context) {
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Delegator delegator = dctx.getDelegator();
        Map<String, Object> result = new HashMap<>();
        GetSellingManagerInventoryRequestType req = new GetSellingManagerInventoryRequestType();
        GetSellingManagerInventoryResponseType resp = null;

        if (context.get("productStoreId") != null) {
            GetSellingManagerInventoryCall call = new GetSellingManagerInventoryCall(EbayStoreHelper.getApiContext((String) context.get("productStoreId"), locale, delegator));

            try {
                SellingManagerProductType[] returnedSellingManagerProductType = null;
                resp = (GetSellingManagerInventoryResponseType)call.execute(req);
                if (resp != null && "SUCCESS".equals(resp.getAck().toString())) {
                    returnedSellingManagerProductType = resp.getSellingManagerProduct();
                    for (SellingManagerProductType sellingManagerProductType : returnedSellingManagerProductType) {
                       SellingManagerProductDetailsType prodDetailType = sellingManagerProductType.getSellingManagerProductDetails();
                       int qty = prodDetailType.getQuantityAvailable();

                       if (qty == 0) {
                           SellingManagerTemplateDetailsArrayType sellingTempArr = sellingManagerProductType.getSellingManagerTemplateDetailsArray();
                           SellingManagerTemplateDetailsType[] selllingTempType = null;
                           if (UtilValidate.isNotEmpty(sellingTempArr)) {
                               selllingTempType = sellingTempArr.getSellingManagerTemplateDetails();
                           }

                           if (selllingTempType.length > 0) {
                               for (SellingManagerTemplateDetailsType sellingManagerTemplateDetailsType : selllingTempType) {
                                   Long longTemplete = Long.parseLong(sellingManagerTemplateDetailsType.getSaleTemplateID());
                                   DeleteSellingManagerTemplateCall tcall = new DeleteSellingManagerTemplateCall(EbayStoreHelper.getApiContext((String) context.get("productStoreId"), locale, delegator));
                                   DeleteSellingManagerTemplateRequestType treq = new DeleteSellingManagerTemplateRequestType();
                                   DeleteSellingManagerTemplateResponseType tresp = null;
                                   treq.setSaleTemplateID(longTemplete);

                                   tresp = (DeleteSellingManagerTemplateResponseType) tcall.execute(treq);
                                   if (tresp != null && "SUCCESS".equals(tresp.getAck().toString())) {
                                       result = ServiceUtil.returnSuccess();
                                   } else {
                                       EbayStoreHelper.createErrorLogMessage(userLogin, dctx.getDispatcher(), context.get("productStoreId").toString(), tresp.getAck().toString(), "Delete selling manager template : autoBlockItemsOutOfStock", tresp.getErrors(0).getLongMessage());
                                   }
                               }
                           }
                       }
                    }
                    result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
                } else {
                    EbayStoreHelper.createErrorLogMessage(userLogin, dctx.getDispatcher(), context.get("productStoreId").toString(), resp.getAck().toString(), "Get selling manager inventory : autoBlockItemsOutOfStock", resp.getErrors(0).getLongMessage());
                }
                result = ServiceUtil.returnSuccess();
            } catch (ApiException | SdkException | SdkSoapException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static Map<String, Object> autoRelistingItems(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> itemObject = new HashMap<>();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        try {
            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
            EntityCondition expression1 = EntityCondition.makeCondition("autoRelisting", EntityOperator.EQUALS, "Y");
            EntityCondition expression2 = EntityCondition.makeCondition("endDateTime", EntityOperator.LESS_THAN, UtilDateTime.nowTimestamp());
            EntityCondition expression3 = EntityCondition.makeCondition("itemId", EntityOperator.NOT_EQUAL, null);
            List<EntityCondition> expressions = new LinkedList<>();
            expressions.add(expression1);
            expressions.add(expression2);
            expressions.add(expression3);
            EntityCondition cond = EntityCondition.makeCondition(expressions, EntityOperator.AND);
            List<GenericValue> ebayProductListings = EntityQuery.use(delegator).from("EbayProductListing").where(expressions).queryList();
            for (GenericValue productListing : ebayProductListings) {
                Map<String, Object> inMap = new HashMap<>();
                AddItemCall addItemCall = new AddItemCall(EbayStoreHelper.getApiContext((String) context.get("productStoreId"), locale, delegator));
                GenericValue ebayProductListing = productListing;
                ItemType item = EbayStoreHelper.prepareAddItem(delegator, ebayProductListing);
                addItemCall.setItem(item);
                itemObject.put("addItemCall", addItemCall);
                itemObject.put("productListingId", ebayProductListing.getString("productListingId"));
                inMap.put("itemObject", itemObject);
                inMap.put("userLogin", userLogin);
                Map<String, Object> result = dispatcher.runSync("exportProductEachItem", inMap);
                if (ServiceUtil.isError(result)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
                }
                String success = (String) result.get("responseMessage");
                if ("success".equals(success)) {
                    String duration = item.getListingDuration();
                    if (duration.length() > 4) {
                        Timestamp startDateTime = UtilDateTime.nowTimestamp();
                        int durationInt = Integer.parseInt(duration.replace("DAYS_", ""));
                        Timestamp endDateTime = UtilDateTime.addDaysToTimestamp(startDateTime, durationInt);
                        ebayProductListing.set("startDateTime", startDateTime);
                        ebayProductListing.set("endDateTime", endDateTime);
                        ebayProductListing.store();
                    }
                }
            }
        } catch (GenericEntityException | GenericServiceException ge) {
            return ServiceUtil.returnError(ge.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }
    public static Map<String, Object> autoBestOffer(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        try {
            String productStoreId = (String) context.get("productStoreId");
            GenericValue ebayProductStorePref = EntityQuery.use(delegator).from("EbayProductStorePref").where("productStoreId", productStoreId, "autoPrefEnumId", "EBAY_AUTO_BEST_OFFER").queryOne();
            String parentPrefCondId = ebayProductStorePref.getString("parentPrefCondId");
            List<GenericValue> ebayProductStorePrefCond = EntityQuery.use(delegator).from("EbayProductStorePrefCond").where("parentPrefCondId", parentPrefCondId).queryList();
            //Parameters
            String priceType = ebayProductStorePrefCond.get(0).getString("acceptanceCondition");
            String acceptBestOfferValue = ebayProductStorePrefCond.get(1).getString("acceptanceCondition");
            String rejectOffer = ebayProductStorePrefCond.get(2).getString("acceptanceCondition");
            String ignoreOfferMessage = ebayProductStorePrefCond.get(3).getString("acceptanceCondition");
            String rejectGreaterEnable = ebayProductStorePrefCond.get(4).getString("acceptanceCondition");
            String greaterValue = ebayProductStorePrefCond.get(5).getString("acceptanceCondition");
            String lessValue = ebayProductStorePrefCond.get(6).getString("acceptanceCondition");
            String rejectGreaterMsg = ebayProductStorePrefCond.get(7).getString("acceptanceCondition");
            String rejectLessEnable = ebayProductStorePrefCond.get(8).getString("acceptanceCondition");
            String lessThanValue = ebayProductStorePrefCond.get(9).getString("acceptanceCondition");
            String rejectLessMsg = ebayProductStorePrefCond.get(10).getString("acceptanceCondition");
            //case parameter to double type
            BigDecimal acceptPercentValue = new BigDecimal(acceptBestOfferValue);
            BigDecimal greaterPercentValue = new BigDecimal(greaterValue);
            BigDecimal lessThanPercentValue = new BigDecimal(lessValue);
            BigDecimal rejectPercentValue = new BigDecimal(lessThanValue);

            ApiContext apiContext = EbayStoreHelper.getApiContext(productStoreId, locale, delegator);
            //GetMysbaySellingCall for get total page
            GetMyeBaySellingCall getTotalPage = new GetMyeBaySellingCall(apiContext);
            ItemListCustomizationType itemListType = new ItemListCustomizationType();
            itemListType.setInclude(Boolean.TRUE);
            itemListType.setSort(ItemSortTypeCodeType.ITEM_ID_DESCENDING);
            itemListType.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);
            DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[] {
                DetailLevelCodeType.RETURN_ALL,
                DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                DetailLevelCodeType.ITEM_RETURN_DESCRIPTION
            };
            getTotalPage.setDetailLevel(detailLevels);
            getTotalPage.setActiveList(itemListType);
            getTotalPage.getMyeBaySelling();
            int totalPage = getTotalPage.getReturnedActiveList().getPaginationResult().getTotalNumberOfPages();
            for (int t = 1; t <= totalPage; t++) {
                //GetMyebaySellingCall for get item that is sold on store
                GetMyeBaySellingCall ebaySelling = new GetMyeBaySellingCall(apiContext);
                //Set type of item
                ItemListCustomizationType itemList = new ItemListCustomizationType();
                itemList.setInclude(Boolean.TRUE);
                itemListType.setSort(ItemSortTypeCodeType.ITEM_ID_DESCENDING);
                itemListType.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);

                PaginationType page = new PaginationType();
                page.setPageNumber(t);
                itemList.setPagination(page);
                itemList.setListingType(ListingTypeCodeType.FIXED_PRICE_ITEM);

                DetailLevelCodeType[] detailLevel = new DetailLevelCodeType[] {
                        DetailLevelCodeType.RETURN_ALL,
                        DetailLevelCodeType.ITEM_RETURN_ATTRIBUTES,
                        DetailLevelCodeType.ITEM_RETURN_DESCRIPTION,
                        DetailLevelCodeType.RETURN_HEADERS,
                        DetailLevelCodeType.RETURN_MESSAGES
                };
                ebaySelling.setDetailLevel(detailLevel);
                ebaySelling.setActiveList(itemList);
                ebaySelling.getMyeBaySelling();
                PaginatedItemArrayType itemListCustomizationType = ebaySelling.getReturnedActiveList();
                ItemArrayType itemArrayType = itemListCustomizationType.getItemArray();
                int itemArrayTypeSize = itemArrayType.getItemLength();

                //Loop for get item
                for (int itemCount = 0; itemCount < itemArrayTypeSize; itemCount++) {
                    ItemType item = itemArrayType.getItem(itemCount);
                    String itemID = item.getItemID();
                    Double buyItNowPrice = item.getBuyItNowPrice().getValue();
                    GetItemCall getItem = new GetItemCall(apiContext);
                    getItem.setDetailLevel(detailLevel);
                    getItem.getItem(itemID);
                    String SKUItem = getItem.getSKU();
                    ItemType itemBestOffer = getItem.getReturnedItem();
                    BestOfferDetailsType bestOfferDetailsType = itemBestOffer.getBestOfferDetails();
                    int inventoryQuantityItem = item.getQuantityAvailable();  //Quantity of the item
                    int bestOfferCount = itemBestOffer.getBestOfferDetails().getBestOfferCount();
                    Boolean bestOfferIsEnabled = itemBestOffer.getBestOfferDetails().isBestOfferEnabled();
                    //Check value of Best offer Detail not null
                    if ((bestOfferDetailsType != null) && (bestOfferCount > 0) && bestOfferIsEnabled.equals(true)) {
                        //Get base price from kindOfPrice parameter
                        Double doBasePrice = null;
                        if ("BUY_IT_NOW_PRICE".equals(priceType)) {
                            doBasePrice = buyItNowPrice;
                        } else if ("START_PRICE".equals(priceType)) {
                            doBasePrice = itemBestOffer.getStartPrice().getValue();
                        } else if ("RESERVE_PRICE".equals(priceType)) {
                            doBasePrice = itemBestOffer.getReservePrice().getValue();
                        } else if ("RETAIL_PRICE".equals(priceType)) {
                            //ignore
                        } else if ("SELLER_COST".equals(priceType)) {
                            List<GenericValue> supplierProduct = EntityQuery.use(delegator).from("SupplierProduct").where("productId", SKUItem).orderBy("availableFromDate DESC").queryList();
                            String lastPrice = supplierProduct.get(0).getString("lastPrice");
                            doBasePrice = Double.parseDouble(lastPrice);
                        } else if ("SECOND_CHANCE_PRICE".equals(priceType)) {
                            VerifyAddSecondChanceItemCall verifyAddSecondChanceItemCall = new VerifyAddSecondChanceItemCall(apiContext);
                            doBasePrice = verifyAddSecondChanceItemCall.getBuyItNowPrice().getValue();
                        } else if ("STORE_PRICE".equals(priceType)) {
                            //ignore
                        }
                        BigDecimal basePrice = new BigDecimal(doBasePrice);
                        BigDecimal percent = new BigDecimal(100);
                        //Calculate price with base price and percent from parameter
                        BigDecimal acceptPrice = (basePrice.multiply(acceptPercentValue)).divide(percent);
                        BigDecimal greaterPrice = (basePrice.multiply(greaterPercentValue)).divide(percent);
                        BigDecimal lessThanPrice = (basePrice.multiply(lessThanPercentValue)).divide(percent);
                        BigDecimal rejectPrice = (basePrice.multiply(rejectPercentValue)).divide(percent);

                        //GetBestOfferCall for get best offer detail
                        GetBestOffersCall getBestOfferCall = new GetBestOffersCall(apiContext);
                        getBestOfferCall.setItemID(itemID);
                        getBestOfferCall.setDetailLevel(detailLevel);
                        getBestOfferCall.setBestOfferStatus(BestOfferStatusCodeType.ALL);
                        getBestOfferCall.getBestOffers();
                        BestOfferType[] bestOffers = getBestOfferCall.getReturnedBestOffers();
                        List<String> acceptBestOfferIndexId = new LinkedList<>();
                        SortedMap<String, Object> acceptBestOfferIDs = new TreeMap<>();
                        //Loop for get data best offer from buyer
                        RespondToBestOfferCall respondToBestOfferCall = new RespondToBestOfferCall(apiContext);
                        respondToBestOfferCall.setItemID(itemID);
                        for (BestOfferType bestOfferType : bestOffers) {
                            BestOfferStatusCodeType bestOfferStatusCodeType = bestOfferType.getStatus();
                            //Check status of best offer
                            if (bestOfferStatusCodeType == BestOfferStatusCodeType.PENDING) {
                                String bestOfferID = bestOfferType.getBestOfferID();
                                UserType buyer = bestOfferType.getBuyer();
                                String buyerUserID = buyer.getUserID();
                                AmountType price = bestOfferType.getPrice();
                                String offerPrice = Double.toString(price.getValue());
                                Double doCerrentPrice = Double.parseDouble(offerPrice);
                                int offerQuantity = bestOfferType.getQuantity();
                                String[] bestOfferIDs = {bestOfferID};
                                respondToBestOfferCall.setBestOfferIDs(bestOfferIDs);

                                if ("Y".equals(rejectOffer)) {
                                    if (offerQuantity > inventoryQuantityItem) {
                                        respondToBestOfferCall.setSellerResponse("Your order is more than inventory item's Buy-It-Now price.");
                                        respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                        respondToBestOfferCall.respondToBestOffer();
                                        continue;
                                    }
                                }

                                String buyerMessage = bestOfferType.getBuyerMessage();
                                if ("Y".equals(ignoreOfferMessage) && UtilValidate.isNotEmpty(buyerMessage)) {
                                    GenericValue userOfferCheck = EntityQuery.use(delegator).from("EbayUserBestOffer").where("itemId", itemID, "userId", buyerUserID).queryOne();
                                    if (UtilValidate.isEmpty(userOfferCheck)) {
                                        GenericValue ebayUserBestOffer = delegator.makeValue("EbayUserBestOffer");
                                        ebayUserBestOffer.put("productStoreId", productStoreId);
                                        ebayUserBestOffer.put("itemId", itemID);
                                        ebayUserBestOffer.put("userId", buyerUserID);
                                        ebayUserBestOffer.put("bestOfferId", bestOfferID);
                                        ebayUserBestOffer.put("contactStatus", "NOT_CONTACT");
                                        ebayUserBestOffer.create();
                                    }
                                    continue;
                                }
                                BigDecimal cerrentPrice = new BigDecimal(doCerrentPrice);
                                if (cerrentPrice.compareTo(acceptPrice) >= 0) {
                                    acceptBestOfferIndexId.add(bestOfferID);
                                    String Quantity = String.valueOf(offerQuantity);
                                    acceptBestOfferIDs.put(bestOfferID, Quantity);
                                } else if ((cerrentPrice.compareTo(greaterPrice) >= 0) && (cerrentPrice.compareTo(lessThanPrice) <= 0) && "Y".equals(rejectGreaterEnable)) {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.setSellerResponse(rejectGreaterMsg);
                                    respondToBestOfferCall.respondToBestOffer();
                                } else if ((cerrentPrice.compareTo(rejectPrice) <= 0 && "Y".equals(rejectLessEnable))) {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.setSellerResponse(rejectLessMsg);
                                    respondToBestOfferCall.respondToBestOffer();
                                } else {
                                    respondToBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                    respondToBestOfferCall.respondToBestOffer();
                                }
                            }
                        }

                        if (!acceptBestOfferIndexId.isEmpty()) {
                            int quantityAvailable = inventoryQuantityItem;
                            acceptBestOfferIndexId.sort(null);
                            RespondToBestOfferCall respondAcceptBestOfferCall = new RespondToBestOfferCall(apiContext);
                            respondAcceptBestOfferCall.setItemID(itemID);
                            for (String bestOfferIdIndex : acceptBestOfferIndexId) {
                                if (quantityAvailable <= 0) break;
                                Integer offerQuantity = Integer.parseInt(acceptBestOfferIDs.get(bestOfferIdIndex).toString());
                                String[] bestOfferID = { bestOfferIdIndex };
                                respondAcceptBestOfferCall.setBestOfferIDs(bestOfferID);
                                //respondAcceptBestOfferCall.setBestOfferIDs(bestOfferID);
                                if (offerQuantity <= quantityAvailable) {
                                    respondAcceptBestOfferCall.setBestOfferAction(BestOfferActionCodeType.ACCEPT);
                                    quantityAvailable = quantityAvailable - offerQuantity;
                                } else {
                                    respondAcceptBestOfferCall.setBestOfferAction(BestOfferActionCodeType.DECLINE);
                                }
                                respondAcceptBestOfferCall.respondToBestOffer();
                            }
                        }
                    }
                }
            }
        } catch (ApiException e) {
            return ServiceUtil.returnError(e.getMessage());
        } catch (Exception e) {
            return ServiceUtil.returnError(e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }
}
