'use strict';

var redsysConstants = require('*/cartridge/scripts/constants/redsysConstants');
var Transaction = require('dw/system/Transaction');

/**
 * Get credit card name by type
 * @param {string} cardId - Credit card type
 * @returns {string} Card name or id if not exist
 */
function getCreditCardName(cardId) {
    var cards = require('*/cartridge/config/cards');

    var cardObj = !cardId
    ? cards[0]
    : cards.filter(function (card) {
        return card.id === cardId;
    })[0];

    if (!cardObj) {
        return cardId;
    }

    return cardObj.name;
}

/**
 * Get transaction response message by code
 * @param {string} codeId - Code Id
 * @returns {string} Response message of id if not exist
 */
function getResponseByCode(codeId) {
    var codes = require('*/cartridge/config/responseCodes');

    var codeObj = !codeId
    ? codes[0]
    : codes.filter(function (code) {
        return code.id === codeId;
    })[0];

    if (!codeObj) {
        return codeId;
    }

    return codeObj.message;
}

/**
 * Mask credit card number
 * Redsys masks the credit card number in a different way and we need the same mask that SFRA uses
 * @param {string} storedValueCode Stored value code
 * @returns {string} Masked stored value code
 */
function maskCreditCard(storedValueCode) {
    var maskedCreditCard = (new Array(13).join('*')) + storedValueCode.substr(-4);

    return maskedCreditCard;
}


/**
 * List all credit cards saved in wallet and check if the new credit card exists
 * @param {dw.customer.Customer} customer - The current customer
 * @param {Object} srvResponse - payment information returned by Redsys
 * @return {boolean} true if credit card exists, false if not
 */
function existPaymentInstrument(customer, srvResponse) {
    var paymentInstruments = customer.getProfile().getWallet().getPaymentInstruments(redsysConstants.REDSYS_CREDIT_CARD);
    var cardNumber = srvResponse.Ds_Card_Number ? srvResponse.Ds_Card_Number : srvResponse.Ds_CardNumber;
    var maskedCreditCard = maskCreditCard(cardNumber);

    for (var i = 0; i < paymentInstruments.length; i++) {
        var creditcard = paymentInstruments[i];

        if (creditcard.maskedCreditCardNumber === maskedCreditCard &&
            creditcard.creditCardType === getCreditCardName(srvResponse.Ds_Card_Brand)) {
            return true;
        }
    }

    return false;
}


/**
 * Get token of given payment instrument
 * @param {string} UUID - payment information returned by Redsys
 * @param {Object} customer - Current logged in customer
 * @return {string} Token of payment instrument
 */
function getTokenOfPaymentInstrument(UUID, customer) {
    var token = '';

    if (customer && customer.authenticated && UUID) {
        var wallet = customer.getProfile().getWallet();
        var paymentInstruments = wallet.getPaymentInstruments();
        var paymentInstrument = null;
        var paymentInstrumentIterator = paymentInstruments.iterator();

        while (paymentInstrumentIterator.hasNext()) {
            paymentInstrument = paymentInstrumentIterator.next();
            if (paymentInstrument.UUID.equals(UUID) && paymentInstrument.getCreditCardToken()) {
                token = paymentInstrument.getCreditCardToken();
                break;
            }
        }
    }

    return token;
}

/**
 * Saves payment instrument to customers wallet
 * @param {Object} srvResponse - payment information returned by Redsys
 * @param {dw.customer.Customer} customer - The current customer
 * @returns {dw.customer.CustomerPaymentInstrument} newly stored payment Instrument
 */
function savePaymentInstrument(srvResponse, customer) {
    var wallet = customer.getProfile().getWallet();
    var expirationYear = Number(srvResponse.Ds_ExpiryDate.substr(0, 2));
    var expirationMonth = Number(srvResponse.Ds_ExpiryDate.substr(2, 4));
    var cardType = getCreditCardName(srvResponse.Ds_Card_Brand);
    var cardNumber = srvResponse.Ds_Card_Number ? srvResponse.Ds_Card_Number : srvResponse.Ds_CardNumber;

    return Transaction.wrap(function () {
        var storedPaymentInstrument = wallet.createPaymentInstrument(redsysConstants.REDSYS_CREDIT_CARD);

        storedPaymentInstrument.setCreditCardHolder(
           customer.profile.firstName + ' ' + customer.profile.lastName
        );
        storedPaymentInstrument.setCreditCardNumber(
            cardNumber
        );
        storedPaymentInstrument.setCreditCardType(
            cardType
        );
        storedPaymentInstrument.setCreditCardExpirationMonth(
            expirationMonth
        );
        storedPaymentInstrument.setCreditCardExpirationYear(
            expirationYear
        );
        storedPaymentInstrument.setCreditCardToken(
            srvResponse.Ds_Merchant_Identifier
        );

        return storedPaymentInstrument;
    });
}

/**
 * Save the credit card information to login account if save card option is selected
 * @param {Object} req - The request object
 * @param {dw.order.PaymentInstrument} paymentInstrument -  The payment instrument to authorize
 * @param {Object} srvResponse - payment information
 */
function savePaymentInformation(req, paymentInstrument, srvResponse) {
    var CustomerMgr = require('dw/customer/CustomerMgr');
    var redsysHelper = require('*/cartridge/scripts/redsys/helpers/redsysHelper');
    var redsysSession = redsysHelper.parseRedsysSessionData();
    var customer = CustomerMgr.getCustomerByCustomerNumber(
        req.currentCustomer.profile.customerNo
    );

    var existPayment = existPaymentInstrument(customer, srvResponse);

    if (req.currentCustomer.raw.authenticated
        && req.currentCustomer.raw.registered
        && redsysSession.saveCard
        && customer
        && !existPayment
        && (paymentInstrument.paymentMethod === redsysConstants.REDSYS_CREDIT_CARD)
    ) {
        var saveCardResult = savePaymentInstrument(
            srvResponse,
            customer
        );

        req.currentCustomer.wallet.paymentInstruments.push({
            creditCardHolder: saveCardResult.creditCardHolder,
            maskedCreditCardNumber: saveCardResult.maskedCreditCardNumber,
            creditCardType: saveCardResult.creditCardType,
            creditCardExpirationMonth: saveCardResult.creditCardExpirationMonth,
            creditCardExpirationYear: saveCardResult.creditCardExpirationYear,
            UUID: saveCardResult.UUID,
            creditCardNumber: saveCardResult.creditCardNumber,
            raw: saveCardResult
        });
    }
}

/**
 * Save the credit card information to login account if save card option is selected
 * @param {Object} paymentUUID - The saved paymentUUID
 * @param {Object} token - The saved payment token
 * @returns {boolean} true/false
 */
function deletePaymentInstrument(paymentUUID, token) {
    var redsysApi = require('*/cartridge/scripts/redsys/redsysApi');

    var borraPreferenciaResponse = redsysApi.borraPreferencia(paymentUUID, token);
    if (borraPreferenciaResponse.status === redsysConstants.REDSYS_RESPONSE_PASS) {
        return true;
    }

    return false;
}

module.exports = {
    existPaymentInstrument: existPaymentInstrument,
    getTokenOfPaymentInstrument: getTokenOfPaymentInstrument,
    savePaymentInformation: savePaymentInformation,
    savePaymentInstrument: savePaymentInstrument,
    deletePaymentInstrument: deletePaymentInstrument,
    getResponseByCode: getResponseByCode
};

