/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.accounting.thirdparty.gosoftware;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import org.ofbiz.accounting.payment.PaymentGatewayServices;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilNumber;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceUtil;


public class RitaServices {

    public static final String module = RitaServices.class.getName();
    private static int decimals = UtilNumber.getBigDecimalScale("invoice.decimals");
    private static int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding");
    public final static String resource = "AccountingUiLabels";
    public static final String resourceOrder = "OrderUiLabels";

    public static Map<String, Object> ccAuth(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Properties props = buildPccProperties(context);
        RitaApi api = getApi(props, "CREDIT");
        if (api == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaErrorGettingPaymentGatewayConfig", locale));
        }

        try {
            RitaServices.setCreditCardInfo(api, dctx.getDelegator(), context);
        } catch (GeneralException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        // basic tx info
        api.set(RitaApi.TRANS_AMOUNT, getAmountString(context, "processAmount"));
        api.set(RitaApi.INVOICE, context.get("orderId"));

        // command setting
        if ("1".equals(props.getProperty("autoBill"))) {
            // sale
            api.set(RitaApi.COMMAND, "SALE");
        } else {
            // pre-auth
            api.set(RitaApi.COMMAND, "PRE_AUTH");
        }

        // send the transaction
        RitaApi out = null;
        try {
            Debug.log("Sending request to RiTA", module);
            out = api.send();
        } catch (IOException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (out != null) {
            Map<String, Object> result = ServiceUtil.returnSuccess();
            String resultCode = out.get(RitaApi.RESULT);
            boolean passed = false;
            if ("CAPTURED".equals(resultCode)) {
                result.put("authResult", Boolean.TRUE);
                result.put("captureResult", Boolean.TRUE);
                passed = true;
            } else if ("APPROVED".equals(resultCode)) {
                result.put("authCode", out.get(RitaApi.AUTH_CODE));
                result.put("authResult", Boolean.TRUE);
                passed = true;
            } else if ("PROCESSED".equals(resultCode)) {
                result.put("authResult", Boolean.TRUE);
            } else {
                result.put("authResult", Boolean.FALSE);
            }

            result.put("authRefNum", out.get(RitaApi.INTRN_SEQ_NUM) != null ? out.get(RitaApi.INTRN_SEQ_NUM) : "");
            result.put("processAmount", context.get("processAmount"));
            result.put("authCode", out.get(RitaApi.AUTH_CODE));
            result.put("authFlag", out.get(RitaApi.REFERENCE));
            result.put("authMessage", out.get(RitaApi.RESULT));
            result.put("cvCode", out.get(RitaApi.CVV2_CODE));
            result.put("avsCode", out.get(RitaApi.AVS_CODE));

            if (!passed) {
                String respMsg = out.get(RitaApi.RESULT) + " / " + out.get(RitaApi.INTRN_SEQ_NUM);
                result.put("customerRespMsgs", UtilMisc.toList(respMsg));
            }

            if (result.get("captureResult") != null) {
                result.put("captureCode", out.get(RitaApi.AUTH_CODE));
                result.put("captureFlag", out.get(RitaApi.REFERENCE));
                result.put("captureRefNum", out.get(RitaApi.INTRN_SEQ_NUM));
                result.put("captureMessage", out.get(RitaApi.RESULT));
            }

            return result;

        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaResultIsNull", locale));
        }
    }

    public static Map<String, Object> ccCapture(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        Locale locale = (Locale) context.get("locale");

        //lets see if there is a auth transaction already in context
        GenericValue authTransaction = (GenericValue) context.get("authTrans");

        if (authTransaction == null) {
            authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        }

        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotCapture", locale));
        }

        // setup the RiTA Interface
        Properties props = buildPccProperties(context);
        RitaApi api = getApi(props, "CREDIT");
        if (api == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaErrorGettingPaymentGatewayConfig", locale));
        }

        api.set(RitaApi.ORIG_SEQ_NUM, authTransaction.getString("referenceNum"));
        api.set(RitaApi.COMMAND, "COMPLETION");

        // send the transaction
        RitaApi out = null;
        try {
            out = api.send();
        } catch (IOException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (out != null) {
            Map<String, Object> result = ServiceUtil.returnSuccess();
            String resultCode = out.get(RitaApi.RESULT);
            if ("CAPTURED".equals(resultCode)) {
                result.put("captureResult", Boolean.TRUE);
            } else {
                result.put("captureResult", Boolean.FALSE);
            }
            result.put("captureAmount", context.get("captureAmount"));
            result.put("captureRefNum", out.get(RitaApi.INTRN_SEQ_NUM) != null ? out.get(RitaApi.INTRN_SEQ_NUM) : "");
            result.put("captureCode", out.get(RitaApi.AUTH_CODE));
            result.put("captureFlag", out.get(RitaApi.REFERENCE));
            result.put("captureMessage", out.get(RitaApi.RESULT));

            return result;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaResultIsNull", locale));
        }
    }

    public static Map<String, Object> ccVoidRelease(DispatchContext dctx, Map<String, ? extends Object> context) {
        return ccVoid(dctx, context, false);
    }

    public static Map<String, Object> ccVoidRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
        return ccVoid(dctx, context, true);
    }

    private static Map<String, Object> ccVoid(DispatchContext dctx, Map<String, ? extends Object> context, boolean isRefund) {
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        Locale locale = (Locale) context.get("locale");

        //lets see if there is a auth transaction already in context
        GenericValue authTransaction = (GenericValue) context.get("authTrans");

        if (authTransaction == null) {
            authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        }

        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotRelease", locale));
        }

        // setup the RiTA Interface
        Properties props = buildPccProperties(context);
        RitaApi api = getApi(props, "CREDIT");
        if (api == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaErrorGettingPaymentGatewayConfig", locale));
        }

        api.set(RitaApi.TRANS_AMOUNT, getAmountString(context, isRefund ? "refundAmount" : "releaseAmount"));
        api.set(RitaApi.ORIG_SEQ_NUM, authTransaction.getString("referenceNum"));
        api.set(RitaApi.COMMAND, "VOID");

        // check to make sure we are configured for SALE mode
        if (!"1".equals(props.getProperty("autoBill"))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaCannotSupportReleasingPreAuth", locale));
        }

        // send the transaction
        RitaApi out = null;
        try {
            out = api.send();
        } catch (IOException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (out != null) {
            Map<String, Object> result = ServiceUtil.returnSuccess();
            String resultCode = out.get(RitaApi.RESULT);
            if ("VOIDED".equals(resultCode)) {
                result.put(isRefund ? "refundResult" : "releaseResult", Boolean.TRUE);
            } else {
                result.put(isRefund ? "refundResult" : "releaseResult", Boolean.FALSE);
            }
            result.put(isRefund ? "refundAmount" : "releaseAmount", context.get(isRefund ? "refundAmount" : "releaseAmount"));
            result.put(isRefund ? "refundRefNum" : "releaseRefNum", out.get(RitaApi.INTRN_SEQ_NUM) != null ? out.get(RitaApi.INTRN_SEQ_NUM) : "");
            result.put(isRefund ? "refundCode" : "releaseCode", out.get(RitaApi.AUTH_CODE));
            result.put(isRefund ? "refundFlag" : "releaseFlag", out.get(RitaApi.REFERENCE));
            result.put(isRefund ? "refundMessage" : "releaseMessage", out.get(RitaApi.RESULT));

            return result;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaResultIsNull", locale));
        }
    }

    public static Map<String, Object> ccCreditRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        Locale locale = (Locale) context.get("locale");

        //lets see if there is a auth transaction already in context
        GenericValue authTransaction = (GenericValue) context.get("authTrans");

        if (authTransaction == null) {
            authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        }

        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionAuthorizationNotFoundCannotRefund", locale));
        }

        // setup the RiTA Interface
        Properties props = buildPccProperties(context);
        RitaApi api = getApi(props, "CREDIT");
        if (api == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaErrorGettingPaymentGatewayConfig", locale));
        }

        // set the required cc info
        try {
            RitaServices.setCreditCardInfo(api, dctx.getDelegator(), context);
        } catch (GeneralException e) {
            return ServiceUtil.returnError(e.getMessage());
        }

        api.set(RitaApi.TRANS_AMOUNT, getAmountString(context, "refundAmount"));
        api.set(RitaApi.ORIG_SEQ_NUM, authTransaction.getString("referenceNum"));
        api.set(RitaApi.COMMAND, "CREDIT");

        // send the transaction
        RitaApi out = null;
        try {
            out = api.send();
        } catch (IOException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (out != null) {
            Map<String, Object> result = ServiceUtil.returnSuccess();
            String resultCode = out.get(RitaApi.RESULT);
            if ("CAPTURED".equals(resultCode)) {
                result.put("refundResult", Boolean.TRUE);
            } else {
                result.put("refundResult", Boolean.FALSE);
            }
            result.put("refundAmount", context.get("refundAmount"));
            result.put("refundRefNum", out.get(RitaApi.INTRN_SEQ_NUM) != null ? out.get(RitaApi.INTRN_SEQ_NUM) : "");
            result.put("refundCode", out.get(RitaApi.AUTH_CODE));
            result.put("refundFlag", out.get(RitaApi.REFERENCE));
            result.put("refundMessage", out.get(RitaApi.RESULT));

            return result;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingRitaResultIsNull", locale));
        }
    }

    public static Map<String, Object> ccRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        Locale locale = (Locale) context.get("locale");
        GenericValue orderHeader = null;
        try {
            orderHeader = orderPaymentPreference.getRelatedOne("OrderHeader");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderPaymentPreference.getString("orderId")), locale));
        }

        if (orderHeader != null) {
            String terminalId = orderHeader.getString("terminalId");
            boolean isVoid = false;
            if (terminalId != null) {
                Timestamp orderDate = orderHeader.getTimestamp("orderDate");
                GenericValue terminalState = null;
                try {
                    List<GenericValue> states = delegator.findByAnd("PosTerminalState", UtilMisc.toMap("posTerminalId", terminalId));
                    states = EntityUtil.filterByDate(states, UtilDateTime.nowTimestamp(), "openedDate", "closedDate", true);
                    terminalState = EntityUtil.getFirst(states);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }

                // this is the current opened terminal
                if (terminalState != null) {
                    Timestamp openDate = terminalState.getTimestamp("openedDate");
                    // if the order date is after the open date of the current state
                    // the order happend within the current open/close of the terminal
                    if (orderDate.after(openDate)) {
                        isVoid = true;
                    }
                }
            }

            Map<String, Object> refundResp = null;
            try {
                if (isVoid) {
                    refundResp = dispatcher.runSync("ritaCCVoidRefund", context);
                } else {
                    refundResp = dispatcher.runSync("ritaCCCreditRefund", context);
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                        "AccountingRitaErrorServiceException", locale));
            }
            return refundResp;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderPaymentPreference.getString("orderId")), locale));
        }
    }

    private static void setCreditCardInfo(RitaApi api, Delegator delegator, Map<String, ? extends Object> context) throws GeneralException {
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue creditCard = (GenericValue) context.get("creditCard");
        if (creditCard == null) {
            creditCard = delegator.findByPrimaryKey("CreditCard", UtilMisc.toMap("paymentMethodId", orderPaymentPreference.getString("paymentMethodId")));
        }
        if (creditCard != null) {
            List<String> expDateList = StringUtil.split(creditCard.getString("expireDate"), "/");
            String month = expDateList.get(0);
            String year = expDateList.get(1);
            String y2d = year.substring(2);

            String title = creditCard.getString("titleOnCard");
            String fname = creditCard.getString("firstNameOnCard");
            String mname = creditCard.getString("middleNameOnCard");
            String lname = creditCard.getString("lastNameOnCard");
            String sufix = creditCard.getString("suffixOnCard");
            StringBuilder name = new StringBuilder();
            if (UtilValidate.isNotEmpty(title)) {
                name.append(title).append(" ");
            }
            if (UtilValidate.isNotEmpty(fname)) {
                name.append(fname).append(" ");
            }
            if (UtilValidate.isNotEmpty(mname)) {
                name.append(mname).append(" ");
            }
            if (UtilValidate.isNotEmpty(lname)) {
                name.append(lname).append(" ");
            }
            if (UtilValidate.isNotEmpty(sufix)) {
                name.append(sufix);
            }
            String nameOnCard = name.toString().trim();
            String acctNumber = creditCard.getString("cardNumber");
            String cvNum = (String) context.get("cardSecurityCode");

            api.set(RitaApi.ACCT_NUM, acctNumber);
            api.set(RitaApi.EXP_MONTH, month);
            api.set(RitaApi.EXP_YEAR, y2d);
            api.set(RitaApi.CARDHOLDER, nameOnCard);
            if (UtilValidate.isNotEmpty(cvNum)) {
                api.set(RitaApi.CVV2, cvNum);
            }

            // billing address information
            GenericValue billingAddress = (GenericValue) context.get("billingAddress");
            if (billingAddress != null) {
                api.set(RitaApi.CUSTOMER_STREET, billingAddress.getString("address1"));
                api.set(RitaApi.CUSTOMER_ZIP, billingAddress.getString("postalCode"));
            } else {
                String zipCode = orderPaymentPreference.getString("billingPostalCode");
                if (UtilValidate.isNotEmpty(zipCode)) {
                    api.set(RitaApi.CUSTOMER_ZIP, zipCode);
                }
            }

            // set the present flag
            String presentFlag = orderPaymentPreference.getString("presentFlag");
            if (presentFlag == null) {
                presentFlag = "N";
            }
            api.set(RitaApi.PRESENT_FLAG, presentFlag.equals("Y") ? "3" : "1"); // 1, no present, 2 present, 3 swiped
        } else {
            throw new GeneralException("No CreditCard object found");
        }
    }

    private static RitaApi getApi(Properties props) {
        if (props == null) {
            Debug.logError("Cannot load API w/ null properties", module);
            return null;
        }
        String host = props.getProperty("host");
        int port = 0;
        try {
            port = Integer.parseInt(props.getProperty("port"));
        } catch (Exception e) {
            Debug.logError(e, module);
        }
        boolean ssl = props.getProperty("ssl", "N").equals("Y") ? true : false;

        RitaApi api = null;
        if (port > 0 && host != null) {
            api = new RitaApi(host, port, ssl);
        } else {
            api = new RitaApi();
        }

        api.set(RitaApi.CLIENT_ID, props.getProperty("clientID"));
        api.set(RitaApi.USER_ID, props.getProperty("userID"));
        api.set(RitaApi.USER_PW, props.getProperty("userPW"));
        api.set(RitaApi.FORCE_FLAG, props.getProperty("forceTx"));

        return api;
    }

    private static RitaApi getApi(Properties props, String paymentType) {
        RitaApi api = getApi(props);
        api.set(RitaApi.FUNCTION_TYPE, "PAYMENT");
        api.set(RitaApi.PAYMENT_TYPE, paymentType);
        return api;
    }

    private static Properties buildPccProperties(Map<String, ? extends Object> context) {
        String configString = (String) context.get("paymentConfig");
        if (configString == null) {
            configString = "payment.properties";
        }

        String clientId = UtilProperties.getPropertyValue(configString, "payment.rita.clientID");
        String userId = UtilProperties.getPropertyValue(configString, "payment.rita.userID");
        String userPw = UtilProperties.getPropertyValue(configString, "payment.rita.userPW");
        String host = UtilProperties.getPropertyValue(configString, "payment.rita.host");
        String port = UtilProperties.getPropertyValue(configString, "payment.rita.port");
        String ssl = UtilProperties.getPropertyValue(configString, "payment.rita.ssl", "N");
        String autoBill = UtilProperties.getPropertyValue(configString, "payment.rita.autoBill", "0");
        String forceTx = UtilProperties.getPropertyValue(configString, "payment.rita.forceTx", "0");

        // some property checking
        if (UtilValidate.isEmpty(clientId)) {
            Debug.logWarning("The clientID property in [" + configString + "] is not configured", module);
            return null;
        }
        if (UtilValidate.isEmpty(userId)) {
            Debug.logWarning("The userID property in [" + configString + "] is not configured", module);
            return null;
        }
        if (UtilValidate.isEmpty(userPw)) {
            Debug.logWarning("The userPW property in [" + configString + "] is not configured", module);
            return null;
        }

        // create some properties for CS Client
        Properties props = new Properties();
        props.put("clientID", clientId);
        props.put("userID", userId);
        props.put("userPW", userPw);
        props.put("host", host);
        props.put("port", port);
        props.put("ssl", ssl);
        props.put("autoBill", autoBill);
        props.put("forceTx", forceTx);
        Debug.log("Returning properties - " + props, module);

        return props;
    }

    private static String getAmountString(Map<String, ? extends Object> context, String amountField) {
        BigDecimal processAmount = (BigDecimal) context.get(amountField);
        return processAmount.setScale(decimals, rounding).toPlainString();
    }
}
