/*
 * 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.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

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.UtilGenerics;
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.ebay.EbayHelper;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.order.order.OrderChangeHelper;
import org.apache.ofbiz.order.shoppingcart.CheckOutHelper;
import org.apache.ofbiz.order.shoppingcart.ShoppingCart;
import org.apache.ofbiz.order.shoppingcart.ShoppingCartItem;
import org.apache.ofbiz.party.party.PartyWorker;
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 EbayStoreOrder {

    private static final String resource = "EbayUiLabels";
    private static final String module = EbayStoreOrder.class.getName();

    public static Map<String, Object> EbayStoreImportTransaction(DispatchContext dctx, Map<String, Object> context) {
        Map<String, Object> result = new HashMap<String, Object>();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        try {
            if ("Complete".equals(context.get("checkoutStatus").toString()) && "NOT_IMPORT".equals(context.get("importStatus").toString())) {
                if (UtilValidate.isEmpty(context.get("shippingAddressStreet1"))) {
                    context.put("shippingAddressStreet1", context.get("shippingAddressStreet").toString());
                }
                result = dispatcher.runSync("EbayStoreCreateTransactionShoppingCart", context);
            }
        } catch (GenericServiceException e) {
            result = ServiceUtil.returnFailure(e.getMessage());
        }
        result.put("productStoreId", context.get("productStoreId").toString());
        result.put("formSelect", "transaction");
        return result;
    }
    public static Map<String, Object> EbayStoreImportOrder(DispatchContext dctx, Map<String, Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> result = new HashMap<String, Object>();
        if (UtilValidate.isEmpty(context.get("orderId"))) {
            try {
                result = dispatcher.runSync("EbayStoreCreateOrderShoppingCart", context);
            } catch (GenericServiceException e) {
                result = ServiceUtil.returnFailure(e.getMessage());
            }
        }
        result.put("productStoreId", context.get("productStoreId").toString());
        result.put("formSelect", "order");
        return result;
    }
    
    public static Map<String, Object> EbayStoreCreateTransactionShoppingCart(DispatchContext dctx, Map<String, Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Map<String, Object> result = new HashMap<String, Object>();
        
        String productStoreId = context.get("productStoreId").toString();
        String defaultCurrencyUomId = "";
        String payToPartyId = "";
        String facilityId = "";
        
        try {
            if (UtilValidate.isEmpty(productStoreId)) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
            } else {
                GenericValue productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
                if (productStore != null) {
                    defaultCurrencyUomId = productStore.getString("defaultCurrencyUomId");
                    payToPartyId = productStore.getString("payToPartyId");
                    facilityId = productStore.getString("inventoryFacilityId");
                } else {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
                }
            }
            
            ShoppingCart cart = new ShoppingCart(delegator, productStoreId, locale, defaultCurrencyUomId);
            String externalId = context.get("externalId").toString();
            if (UtilValidate.isNotEmpty(externalId)) {
                cart.setExternalId(externalId);
            } else {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreOrder.externalIdNotAvailable", locale));
            }

            cart.setOrderType("SALES_ORDER");
            cart.setChannelType("EBAY_SALES_CHANNEL");
            cart.setUserLogin(userLogin, dispatcher);
            cart.setProductStoreId(productStoreId);

            if (UtilValidate.isNotEmpty(facilityId)) {
                cart.setFacilityId(facilityId);
            }

            String amountStr = context.get("amountPaid").toString();
            BigDecimal amountPaid = new BigDecimal(amountStr);
            if (UtilValidate.isNotEmpty(amountPaid)) {
                amountPaid = new BigDecimal(amountStr);
            }
            cart.addPaymentAmount("EXT_EBAY", amountPaid, externalId, null, true, false, false);

            Timestamp orderDate = UtilDateTime.nowTimestamp();
            if (UtilValidate.isNotEmpty(context.get("createdDate"))) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                Date createdDate = dateFormat.parse((String) context.get("createdDate"));
                orderDate = new Timestamp(createdDate.getTime());
            }
            cart.setOrderDate(orderDate);

            String productId = context.get("productId").toString();
            if (UtilValidate.isEmpty(productId)) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productIdNotAvailable", locale));
            } else {
                GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
                if (UtilValidate.isEmpty(product)) {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productIdDoesNotExist", locale));
                }
            }

            if (UtilValidate.isEmpty(context.get("paidTime"))) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.paymentIsStillNotReceived", locale));
            }

            BigDecimal unitPrice = new BigDecimal(context.get("transactionPrice").toString());
            BigDecimal quantity = new BigDecimal(context.get("quantityPurchased").toString());
            cart.addItemToEnd(productId, null, quantity, unitPrice, null, null, null, "PRODUCT_ORDER_ITEM", dispatcher, Boolean.FALSE, Boolean.FALSE);

            if (UtilValidate.isNotEmpty(payToPartyId)) {
                cart.setBillFromVendorPartyId(payToPartyId);
            }

            String shippingCost = context.get("shippingServiceCost").toString();
            if (UtilValidate.isNotEmpty(shippingCost)) {
                BigDecimal shippingAmount = new BigDecimal(shippingCost);
                if (shippingAmount.doubleValue() > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SHIPPING_CHARGES", cart.getOrderId(), null, null, shippingAmount.doubleValue(), 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }

            String shippingTotalAdditionalCost = context.get("shippingTotalAdditionalCost").toString();
            if (UtilValidate.isNotEmpty(shippingTotalAdditionalCost)) {
                double shippingAdditionalCost = new Double(shippingTotalAdditionalCost).doubleValue();
                if (shippingAdditionalCost > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "MISCELLANEOUS_CHARGE", cart.getOrderId(), null, null, shippingAdditionalCost, 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }

            String salesTaxAmount = context.get("salesTaxAmount").toString();
            String salesTaxPercent = context.get("salesTaxPercent").toString();
            if (UtilValidate.isNotEmpty(salesTaxAmount)) {
                double salesTaxAmountTotal = new Double(salesTaxAmount).doubleValue();
                if (salesTaxAmountTotal > 0) {
                    double salesPercent = 0.0;
                    if (UtilValidate.isNotEmpty(salesTaxPercent)) {
                        salesPercent = new Double(salesTaxPercent).doubleValue();
                    }
                    GenericValue salesTaxAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SALES_TAX", cart.getOrderId(), null, null, salesTaxAmountTotal, salesPercent);
                    if (salesTaxAdjustment != null) {
                        cart.addAdjustment(salesTaxAdjustment);
                    }
                }
            }
            
                Debug.logInfo("Importing new order from eBay", module);
                // set partyId to
                String partyId = null;
                String contactMechId = "";
                GenericValue partyAttribute = null;
                if (UtilValidate.isNotEmpty(context.get("eiasTokenBuyer").toString())) {
                    partyAttribute = EntityQuery.use(delegator).from("PartyAttribute").where("attrValue", context.get("eiasTokenBuyer").toString()).queryFirst();
                }

                // if we get a party, check its contact information.
                if (partyAttribute != null) {
                    partyId = (String) partyAttribute.get("partyId");
                    Debug.logInfo("Found existing party associated to the eBay buyer: " + partyId, module);
                    GenericValue party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();

                    contactMechId = EbayHelper.setShippingAddressContactMech(dispatcher, delegator, party, userLogin, context);
                    String emailBuyer = context.get("emailBuyer").toString();
                    if (!(emailBuyer.equals("") || emailBuyer.equalsIgnoreCase("Invalid Request"))) {
                        EbayHelper.setEmailContactMech(dispatcher, delegator, party, userLogin, context);
                    }
                    EbayHelper.setPhoneContactMech(dispatcher, delegator, party, userLogin, context);
                }

                // create party if none exists already
                if (UtilValidate.isEmpty(partyId)) {
                    Debug.logInfo("Creating new party for the eBay buyer.", module);
                    partyId = EbayHelper.createCustomerParty(dispatcher, context.get("buyerName").toString(), userLogin);
                    if (UtilValidate.isEmpty(partyId)) {
                        Debug.logWarning("Using admin party for the eBay buyer.", module);
                        partyId = "admin";
                    }
                }

                // create new party's contact information
                if (UtilValidate.isEmpty(contactMechId)) {
                    Debug.logInfo("Creating new postal address for party: " + partyId, module);
                    contactMechId = EbayHelper.createAddress(dispatcher, partyId, userLogin, "SHIPPING_LOCATION", context);
                    if (UtilValidate.isEmpty(contactMechId)) {
                        return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreUnableToCreatePostalAddress", locale) + context);
                    }
                    Debug.logInfo("Created postal address: " + contactMechId, module);
                    Debug.logInfo("Creating new phone number for party: " + partyId, module);
                    EbayHelper.createPartyPhone(dispatcher, partyId, context.get("shippingAddressPhone").toString(), userLogin);
                    Debug.logInfo("Creating association to eBay buyer for party: " + partyId, module);
                    EbayHelper.createEbayCustomer(dispatcher, partyId, context.get("ebayUserIdBuyer").toString(), context.get("eiasTokenBuyer").toString(), userLogin);
                    String emailBuyer = context.get("emailBuyer").toString();
                    if (UtilValidate.isNotEmpty(emailBuyer) && !emailBuyer.equalsIgnoreCase("Invalid Request")) {
                        Debug.logInfo("Creating new email for party: " + partyId, module);
                        EbayHelper.createPartyEmail(dispatcher, partyId, emailBuyer, userLogin);
                    }
                }

                Debug.logInfo("Setting cart roles for party: " + partyId, module);
                cart.setBillToCustomerPartyId(partyId);
                cart.setPlacingCustomerPartyId(partyId);
                cart.setShipToCustomerPartyId(partyId);
                cart.setEndUserCustomerPartyId(partyId);

                Debug.logInfo("Setting contact mech in cart: " + contactMechId, module);
                cart.setAllShippingContactMechId(contactMechId);
                cart.setAllMaySplit(Boolean.FALSE);

                Debug.logInfo("Setting shipment method: " + context.get("shippingService").toString(), module);
                EbayHelper.setShipmentMethodType(cart, context.get("shippingService").toString(), productStoreId, delegator);

                cart.makeAllShipGroupInfos();

                // create the order
                Debug.logInfo("Creating CheckOutHelper.", module);
                CheckOutHelper checkout = new CheckOutHelper(dispatcher, delegator, cart);
                Debug.logInfo("Creating order.", module);
                Map<String, Object> orderCreate = checkout.createOrder(userLogin);

                String orderId = orderCreate.get("orderId").toString();
                Debug.logInfo("Created order with id: " + orderId, module);

                // approve the order
                if (UtilValidate.isNotEmpty(orderId)) {
                    Debug.logInfo("Approving order with id: " + orderId, module);
                    boolean approved = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
                    Debug.logInfo("Order approved with result: " + approved, module);

                    // create the payment from the preference
                    if (approved) {
                        Debug.logInfo("Creating payment for approved order.", module);
                        EbayHelper.createPaymentFromPaymentPreferences(delegator, dispatcher, userLogin, orderId, externalId, cart.getOrderDate(), amountPaid, partyId);
                        Debug.logInfo("Payment created.", module);
                    }
                }
        } catch (Exception e) {
            result = ServiceUtil.returnFailure(e.getMessage());
        }
        return result;
    }
    public static Map<String, Object> EbayStoreCreateOrderShoppingCart(DispatchContext dctx, Map<String, Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Map <String, Object> result = new HashMap<String, Object>();

        String productStoreId = context.get("productStoreId").toString();
        String defaultCurrencyUomId = null;
        String payToPartyId = null;
        String facilityId = null;
        try {
            if (productStoreId == null) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
            } else {
                GenericValue productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
                if (productStore != null) {
                    defaultCurrencyUomId = productStore.getString("defaultCurrencyUomId");
                    payToPartyId = productStore.getString("payToPartyId");
                    facilityId = productStore.getString("inventoryFacilityId");
                } else {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
                }
            }
            ShoppingCart cart = new ShoppingCart(delegator, productStoreId, locale, defaultCurrencyUomId);

            // set the external id with the eBay Item Id
            String externalId = (String) context.get("externalId");
            cart.setOrderType("SALES_ORDER");
            cart.setChannelType("EBAY_SALES_CHANNEL");
            cart.setUserLogin(userLogin, dispatcher);
            cart.setProductStoreId(productStoreId);

            if (UtilValidate.isNotEmpty(facilityId)) {
                cart.setFacilityId(facilityId);
            }

            String amountStr = (String) context.get("amountPaid");
            BigDecimal amountPaid = BigDecimal.ZERO;
            if (UtilValidate.isNotEmpty(amountStr)) {
                amountPaid = new BigDecimal(amountStr);
            }
            cart.addPaymentAmount("EXT_EBAY", amountPaid, externalId, null, true, false, false);
            Timestamp orderDate = UtilDateTime.nowTimestamp();
            if (UtilValidate.isNotEmpty(context.get("createdDate"))) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                Date createdDate = dateFormat.parse((String) context.get("createdDate"));
                orderDate = new Timestamp(createdDate.getTime());
            }

            cart.setOrderDate(orderDate);
            // Before import the order from eBay to OFBiz is mandatory that the payment has be received
            String paidTime = (String) context.get("paidTime");
            if (UtilValidate.isEmpty(paidTime)) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "ordersImportFromEbay.paymentIsStillNotReceived", locale));
            }

            List<Map<String, Object>> orderItemList = UtilGenerics.checkList(context.get("orderItemList"));
            Iterator<Map<String, Object>> orderItemIter = orderItemList.iterator();
            while (orderItemIter.hasNext()) {
                Map<String, Object> orderItem = orderItemIter.next();
                addItem(cart, orderItem, dispatcher, delegator, 0);
            }

            // set partyId from
            if (UtilValidate.isNotEmpty(payToPartyId)) {
                cart.setBillFromVendorPartyId(payToPartyId);
            }

            Map<String, Object> shippingServiceSelectedCtx =  UtilGenerics.checkMap(context.get("shippingServiceSelectedCtx"));
            if (UtilValidate.isNotEmpty(shippingServiceSelectedCtx.get("shippingServiceCost"))) {
                BigDecimal shippingAmount = new BigDecimal(shippingServiceSelectedCtx.get("shippingServiceCost").toString());
                if (shippingAmount.doubleValue() > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SHIPPING_CHARGES", cart.getOrderId(), null, null, shippingAmount.doubleValue(), 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }

            // Apply additional shipping costs as order adjustment
            if (UtilValidate.isNotEmpty(shippingServiceSelectedCtx.get("shippingTotalAdditionalCost"))) {
                BigDecimal shippingAdditionalCost = new BigDecimal(shippingServiceSelectedCtx.get("shippingTotalAdditionalCost").toString());
                if (shippingAdditionalCost.doubleValue() > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "MISCELLANEOUS_CHARGE", cart.getOrderId(), null, null, shippingAdditionalCost.doubleValue(), 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }

            // Apply sales tax as order adjustment
            Map<String, Object> shippingDetailsCtx = UtilGenerics.checkMap(context.get("shippingDetailsCtx"));
            if (UtilValidate.isNotEmpty(shippingDetailsCtx.get("salesTaxAmount"))) {
                BigDecimal salesTaxAmount = new BigDecimal(shippingDetailsCtx.get("salesTaxAmount").toString());
                if (salesTaxAmount.doubleValue() > 0) {
                    double salesPercent = 0.0;
                    if (UtilValidate.isNotEmpty(shippingDetailsCtx.get("salesTaxPercent"))) {
                        salesPercent = new Double(shippingDetailsCtx.get("salesTaxPercent").toString()).doubleValue();
                    }
                    GenericValue salesTaxAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SALES_TAX", cart.getOrderId(), null, null, salesTaxAmount.doubleValue(), salesPercent);
                    if (salesTaxAdjustment != null) {
                        cart.addAdjustment(salesTaxAdjustment);
                    }
                }
            }

            Debug.logInfo("Importing new order from eBay", module);
            // set partyId to
            String partyId = null;
            String contactMechId = null;

            Map<String, Object> shippingAddressCtx = UtilGenerics.checkMap(context.get("shippingAddressCtx"));
            if (UtilValidate.isNotEmpty(shippingAddressCtx)) {
                String buyerName = (String) shippingAddressCtx.get("buyerName");
                String firstName = buyerName.substring(0, buyerName.indexOf(" "));
                String lastName = buyerName.substring(buyerName.indexOf(" ")+1);

                String country = (String) shippingAddressCtx.get("shippingAddressCountry");
                String state = (String) shippingAddressCtx.get("shippingAddressStateOrProvince");
                String city = (String) shippingAddressCtx.get("shippingAddressCityName");
                EbayHelper.correctCityStateCountry(dispatcher, shippingAddressCtx, city, state, country);
                String shippingAddressStreet = null;
                if (UtilValidate.isEmpty(shippingAddressCtx.get("shippingAddressStreet1"))) {
                    shippingAddressStreet = shippingAddressCtx.get("shippingAddressStreet").toString();
                    shippingAddressCtx.put("shippingAddressStreet1", shippingAddressStreet);
                } else {
                    shippingAddressStreet = shippingAddressCtx.get("shippingAddressStreet1").toString();
                }

                List<GenericValue> shipInfo = PartyWorker.findMatchingPersonPostalAddresses(delegator, shippingAddressStreet,
                        (UtilValidate.isEmpty(shippingAddressCtx.get("shippingAddressStreet2")) ? null : shippingAddressCtx.get("shippingAddressStreet2").toString()), shippingAddressCtx.get("city").toString(), shippingAddressCtx.get("stateProvinceGeoId").toString(),
                        shippingAddressCtx.get("shippingAddressPostalCode").toString(), null, shippingAddressCtx.get("countryGeoId").toString(), firstName, null, lastName);
                if (UtilValidate.isNotEmpty(shipInfo)) {
                    GenericValue first = EntityUtil.getFirst(shipInfo);
                    partyId = first.getString("partyId");
                    Debug.logInfo("Existing shipping address found for : (party: " + partyId + ")", module);
                }
            }

            // If matching party not found then try to find partyId from PartyAttribute entity.
            GenericValue partyAttribute = null;
            if (UtilValidate.isNotEmpty(context.get("eiasTokenBuyer"))) {
                partyAttribute = EntityQuery.use(delegator).from("PartyAttribute").where("attrValue", (String) context.get("eiasTokenBuyer")).queryFirst();
                if (partyAttribute != null) {
                    partyId = (String) partyAttribute.get("partyId");
                }
            }

            // if we get a party, check its contact information.
            if (UtilValidate.isNotEmpty(partyId)) {
                Debug.logInfo("Found existing party associated to the eBay buyer: " + partyId, module);
                GenericValue party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();

                contactMechId = EbayHelper.setShippingAddressContactMech(dispatcher, delegator, party, userLogin, shippingAddressCtx);
                String emailBuyer = (String) context.get("emailBuyer");
                if (!(emailBuyer.equals("") || emailBuyer.equalsIgnoreCase("Invalid Request"))) {
                    EbayHelper.setEmailContactMech(dispatcher, delegator, party, userLogin, context);
                }
                EbayHelper.setPhoneContactMech(dispatcher, delegator, party, userLogin, shippingAddressCtx);
            }

            // create party if none exists already
            if (UtilValidate.isEmpty(partyId)) {
                Debug.logInfo("Creating new party for the eBay buyer.", module);
                partyId = EbayHelper.createCustomerParty(dispatcher, (String) shippingAddressCtx.get("buyerName"), userLogin);
                if (UtilValidate.isEmpty(partyId)) {
                    Debug.logWarning("Using admin party for the eBay buyer.", module);
                    partyId = "admin";
                }
            }

            // create new party's contact information
            if (UtilValidate.isEmpty(contactMechId)) {

                Debug.logInfo("Creating new postal address for party: " + partyId, module);
                contactMechId = EbayHelper.createAddress(dispatcher, partyId, userLogin, "SHIPPING_LOCATION", shippingAddressCtx);
                if (UtilValidate.isEmpty(contactMechId)) {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "EbayStoreUnableToCreatePostalAddress", locale) + shippingAddressCtx);
                }
                Debug.logInfo("Created postal address: " + contactMechId, module);
                Debug.logInfo("Creating new phone number for party: " + partyId, module);
                EbayHelper.createPartyPhone(dispatcher, partyId, (String) shippingAddressCtx.get("shippingAddressPhone"), userLogin);
                Debug.logInfo("Creating association to eBay buyer for party: " + partyId, module);
                EbayHelper.createEbayCustomer(dispatcher, partyId, (String) context.get("ebayUserIdBuyer"), null, userLogin);
                String emailBuyer = (String) context.get("emailBuyer");
                if (UtilValidate.isNotEmpty(emailBuyer) && !emailBuyer.equalsIgnoreCase("Invalid Request")) {
                    Debug.logInfo("Creating new email for party: " + partyId, module);
                    EbayHelper.createPartyEmail(dispatcher, partyId, emailBuyer, userLogin);
                }
            }

            Debug.logInfo("Setting cart roles for party: " + partyId, module);
            cart.setBillToCustomerPartyId(partyId);
            cart.setPlacingCustomerPartyId(partyId);
            cart.setShipToCustomerPartyId(partyId);
            cart.setEndUserCustomerPartyId(partyId);

            Debug.logInfo("Setting contact mech in cart: " + contactMechId, module);
            cart.setAllShippingContactMechId(contactMechId);
            cart.setAllMaySplit(Boolean.FALSE);

            Debug.logInfo("Setting shipment method: " + (String) shippingServiceSelectedCtx.get("shippingService"), module);
            EbayHelper.setShipmentMethodType(cart, (String) shippingServiceSelectedCtx.get("shippingService"), productStoreId, delegator);
            cart.makeAllShipGroupInfos();

            // create the order
            Debug.logInfo("Creating CheckOutHelper.", module);
            CheckOutHelper checkout = new CheckOutHelper(dispatcher, delegator, cart);
            Debug.logInfo("Creating order.", module);
            Map<?, ?> orderCreate = checkout.createOrder(userLogin);

            if ("error".equals(orderCreate.get("responseMessage"))) {
                List<String> errorMessageList = UtilGenerics.checkList(orderCreate.get("errorMessageList"), String.class);
                return ServiceUtil.returnError(errorMessageList);
            }
            String orderId = (String) orderCreate.get("orderId");
            Debug.logInfo("Created order with id: " + orderId, module);

            // approve the order
            if (UtilValidate.isNotEmpty(orderId)) {
                Debug.logInfo("Approving order with id: " + orderId, module);
                boolean approved = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
                Debug.logInfo("Order approved with result: " + approved, module);

                // create the payment from the preference
                if (approved) {
                    Debug.logInfo("Creating payment for approved order.", module);
                    EbayHelper.createPaymentFromPaymentPreferences(delegator, dispatcher, userLogin, orderId, externalId, cart.getOrderDate(), amountPaid, partyId);
                    Debug.logInfo("Payment created.", module);
                }
                result = ServiceUtil.returnFailure(UtilProperties.getMessage("EbayStoreUiLabels", "EbayOrderCreatedSuccessfully", UtilMisc.toMap("orderId", orderId, "externalId", externalId), locale));
            }
        } catch (Exception e) {
            result = ServiceUtil.returnFailure(e.getMessage());
        }
        return result;
    }

    private static void addItem(ShoppingCart cart, Map<String, Object> orderItem, LocalDispatcher dispatcher, Delegator delegator, int groupIdx) throws GeneralException {
        String productId = orderItem.get("productId").toString();
        GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
        if (UtilValidate.isEmpty(product)) {
            Debug.logError("The product having ID (" + productId + ") is misssing in the system.", module);
        }
        BigDecimal qty = new BigDecimal(orderItem.get("quantity").toString());
        String itemPrice = orderItem.get("transactionPrice").toString();
        if (UtilValidate.isEmpty(itemPrice)) {
            itemPrice = orderItem.get("amount").toString();
        }
        BigDecimal price = new BigDecimal(itemPrice);
        price = price.setScale(ShoppingCart.scale, ShoppingCart.rounding);

        Map<String, Object> attrs = new HashMap<String, Object>();
        attrs.put("shipGroup", groupIdx);

        int idx = cart.addItemToEnd(productId, null, qty, null, null, attrs, null, null, dispatcher, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE);
        ShoppingCartItem cartItem = cart.findCartItem(idx);
        cartItem.setQuantity(qty, dispatcher, cart, true, false);
        // locate the price verify it matches the expected price
        BigDecimal cartPrice = cartItem.getBasePrice();
        cartPrice = cartPrice.setScale(ShoppingCart.scale, ShoppingCart.rounding);
        if (price.doubleValue() != cartPrice.doubleValue()) {
            // does not match; honor the price but hold the order for manual review
            cartItem.setIsModifiedPrice(true);
            cartItem.setBasePrice(price);
            cart.setHoldOrder(true);
            cart.addInternalOrderNote("Price received [" + price + "] (for item # " + productId + ") from eBay Checkout does not match the price in the database [" + cartPrice + "]. Order is held for manual review.");
        }
        // assign the item to its ship group
        cart.setItemShipGroupQty(cartItem, qty, groupIdx);
    }
}
