'use strict';

var collections = require('*/cartridge/scripts/util/collections');
var Transaction = require('dw/system/Transaction');
var redsysApi = require('*/cartridge/scripts/redsys/redsysApi');
var redsysConstants = require('*/cartridge/scripts/constants/redsysConstants');
var Logger = require('dw/system/Logger');
var logger = Logger.getLogger('Redsys', 'creditCard');

/**
 * Verifies that entered Redsys Credit Card information is valid. If the information is valid a
 * Redsys Credit Card payment instrument is created
 * @param {dw.order.Basket} basket Current users's basket
 * @return {Object} returns an error object
 */
function Handle(basket) {
    var currentBasket = basket;
    var amount = basket.totalGrossPrice;

    try {
        Transaction.wrap(function () {
            var paymentInstruments = currentBasket.getPaymentInstruments();

            collections.forEach(paymentInstruments, function (item) {
                currentBasket.removePaymentInstrument(item);
            });

            currentBasket.createPaymentInstrument(
                redsysConstants.REDSYS_CREDIT_CARD, amount
            );
        });
    } catch (e) {
        logger.error('Error creating payment instrument: {0}', redsysConstants.REDSYS_CREDIT_CARD);
    }

    return { fieldErrors: {}, serverErrors: [], error: false };
}


/**
 * Authorizes a payment using Redsys Credit Card.
 * @param {number} orderNumber - The current order's number
 * @param {dw.order.Order} order - Customers's order
 * @param {dw.order.PaymentInstrument} paymentInstrument -  The payment instrument to authorize
 * @param {dw.order.PaymentProcessor} paymentProcessor -  The payment processor of the current payment method
 * @return {Object} returns an error object
 */
function Authorize(orderNumber, order, paymentInstrument, paymentProcessor) {
    var Resource = require('dw/web/Resource');
    var redsysHelper = require('*/cartridge/scripts/redsys/helpers/redsysHelper.js');
    var redsysCreditCardPreferences = redsysHelper.getRedsysCreditCardPreferences();
    var redsysSession = redsysHelper.parseRedsysSessionData();
    var serverErrors = [];
    var fieldErrors = {};
    var error = true;
    var trataPeticionResponse = null;
    var trataPeticionResponseObj = null;
    var challenge = false;
    var signature = null;

    // Only to inSite payment
    if (redsysCreditCardPreferences.integrationMode === redsysConstants.REDSYS_INTEGRATION_INSITE) {
        // Request to Redsys API to authorize payment
        var iniciaPeticionResponseObj = redsysApi.iniciaPeticion(order);
        var iniciaPeticionResponse = iniciaPeticionResponseObj.response;

        if (iniciaPeticionResponseObj.status === redsysConstants.REDSYS_RESPONSE_FAIL) {
            error = true;
            serverErrors.push(
                Resource.msg('error.technical', 'checkout', null)
            );
        } else {
            trataPeticionResponseObj = redsysApi.trataPeticion(iniciaPeticionResponse, order);
            trataPeticionResponse = trataPeticionResponseObj.response;
            signature = trataPeticionResponseObj.signature;
            if (trataPeticionResponseObj.status === redsysConstants.REDSYS_RESPONSE_FAIL) {
                error = true;
                serverErrors.push(
                    Resource.msg('error.technical', 'checkout', null)
                );
            }

            if (trataPeticionResponseObj.status === redsysConstants.REDSYS_RESPONSE_PASS &&
                trataPeticionResponseObj.typeOfResponse === redsysConstants.REDSYS_EMV3DS_CHALLENGE_REQUEST) {
                challenge = true;
                var CustomObjectMgr = require('dw/object/CustomObjectMgr');
                try {
                    Transaction.begin();
                    var CustomObj = CustomObjectMgr.createCustomObject('RedsysNotifications', order.orderNo);
                    CustomObj.custom.amount = trataPeticionResponse.Ds_Amount;
                    CustomObj.custom.protocolVersion = iniciaPeticionResponse.Ds_EMV3DS.protocolVersion;
                    CustomObj.custom.threeDSServerTransID = iniciaPeticionResponse.Ds_EMV3DS.threeDSServerTransID;
                    CustomObj.custom.threeDSMethodURL = iniciaPeticionResponse.Ds_EMV3DS.threeDSMethodURL ? iniciaPeticionResponse.Ds_EMV3DS.threeDSMethodURL : null;
                    CustomObj.custom.acsURL = trataPeticionResponse.Ds_EMV3DS.acsURL ? trataPeticionResponse.Ds_EMV3DS.acsURL : null;
                    CustomObj.custom.MD = trataPeticionResponse.Ds_EMV3DS.MD ? trataPeticionResponse.Ds_EMV3DS.MD : null;
                    CustomObj.custom.PaReq = trataPeticionResponse.Ds_EMV3DS.PAReq ? trataPeticionResponse.Ds_EMV3DS.PAReq : null;
                    CustomObj.custom.creq = trataPeticionResponse.Ds_EMV3DS.creq ? trataPeticionResponse.Ds_EMV3DS.creq : null;
                    CustomObj.custom.creditCardToken = redsysSession.creditCardToken ? redsysSession.creditCardToken : null;
                    CustomObj.custom.storedPaymentUUID = redsysSession.storedPaymentUUID ? redsysSession.storedPaymentUUID : null;
                    Transaction.commit();
                    error = false;
                } catch (err) {
                    logger.error('Error creating RedsysNotifications object: {0}', err);
                }
            }
        }
    }

    try {
        Transaction.wrap(function () {
            paymentInstrument.paymentTransaction.setTransactionID(orderNumber);
            paymentInstrument.paymentTransaction.setPaymentProcessor(paymentProcessor);
            redsysSession.orderNo = null;
            error = false;
        });
    } catch (e) {
        error = true;
        serverErrors.push(
            Resource.msg('error.technical', 'checkout', null)
        );
    }

    return {
        challenge: challenge,
        trataPeticionResponse: trataPeticionResponseObj,
        signature: signature,
        fieldErrors: fieldErrors,
        serverErrors: serverErrors,
        error: error
    };
}

exports.Handle = Handle;
exports.Authorize = Authorize;
