Source: ZEventsApiCreditCards/ZEventsApiCreditCards.js

import ifPromise from 'onyx-common/ifPromise'
import stripWhitespace from 'onyx-common/stripWhitespace'

const ZEventsApiEvent = ({ prototype }) => {
  prototype.encryptCreditCardNumber = function (cardNumber) {
    const finalCardNumber = this.normalizeCreditCardNumber(cardNumber)
    return this.encrypt({ input: finalCardNumber })
  }

  prototype.normalizeCreditCardNumber = function (cardNumber) {
    return stripWhitespace(cardNumber)
  }

  prototype.maskCreditCardNumber = function (cardNumber) {
    const finalCardNumber = this.normalizeCreditCardNumber(cardNumber)
    return this.getLastFour(finalCardNumber)
  }

  prototype.normalizeCreditCard = function (entry) {
    const data = this.normalizeData(entry)

    const mapCreditCard = {
      id: ['id', val => parseInt(val)],
      last_four: 'lastFour',
      card_type: 'cardType',
      default: ['isDefault', val => !!val],
      expiration_month: 'expirationMonth',
      expiration_year: 'expirationYear'
    }

    return this.filterAndMapProps(data, mapCreditCard)
  }

  prototype._createCreditCard = function ({ userId, ...rest }) {
    const payload = {
      url: this.getUrl(`/api/v1/users/${userId}/credit_cards`),
      method: 'POST',
      requestType: 'json',
      data: rest
    }

    return this.authenticatedFetchWrap(payload)
  }

  /**
   * @typedef {object} CreditCard
   * @property {number} id - credit card id
   * @property {string} cardType - type of card, visa, discover, amex, mc
   * @property {string} lastFour - last four digits of card
   * @property {number} expirationMonth - expiration month (1-12)
   * @property {number} expirationYear - expiration year
   * @property {boolean} isDefault - is this the default payment method?
   */

  /**
   * @typedef {object} Address
   * @property {string} line1 - line1 of address
   * @property {string} city - city
   * @property {string} state - state
   * @property {string} country - country
   * @property {string} zipCode - zipCode
   */

  /**
   * @function createCreditCard
   * @param {object} payload - The payload
   * @param {string} [payload.userId='me'] - userid to assign
   * @param {string} payload.nameOnCard - name on card
   * @param {string} payload.cardNumber - credit card number
   * @param {number} payload.expirationMonth - exp month
   * @param {number} payload.expirationYear - exp year
   * @param {number} payload.ccv - card ccv
   * @param {string} payload.cardType - visa/mc/discover/amex card type
   * @param {Address} payload.address - address object
   * @param {boolean} payload.isDefault - whether or not default
   * @returns {CreditCard} - new credit card entity
   * @example
   *
   * createCreditCard({
   *   nameOnCard: 'Primary Checking',
   *   cardNumber: 'Joe Jones',
   *   expirationMonth: '1212121212121',
   *   expirationYear: '123444332422223'
   *   ccv: '123444332422223'
   *   cardType: '123444332422223'
   *   address: {
   *     line1: '123 foo street',
   *     city: 'Flavortown',
   *     state: 'ID',
   *     country: 'US',
   *     zipCode: '83842'
   *   }
   * })
   */

  prototype.createCreditCard = function (payload) {
    const {
      userId,
      nameOnCard,
      cardNumber,
      expirationYear,
      expirationMonth,
      ccv,
      cardType,
      address,
      isDefault
    } = payload
    const finalPayload = {
      userId: this.normalizeUserId(userId),
      credit_card: {
        name: nameOnCard,
        default: !!isDefault,
        expiration_year: expirationYear,
        expiration_month: expirationMonth,
        gateway_cvv: ccv,
        address: address.line1,
        city: address.city,
        state: address.state,
        country: address.country,
        zipcode: address.zipCode,
        card_type: cardType,
        encrypted_card_number: this.encryptCreditCardNumber(cardNumber),
        last_four: this.maskCreditCardNumber(cardNumber)
      }
    }

    const raw = ifPromise(payload, () => this._createCreditCard(finalPayload))
    return raw
      .then(res => this.normalizeCreditCard(res.data))
      .catch(error => this.onError('createCreditCard', error))
  }

  prototype._deleteCreditCard = function ({ userId, id }) {
    const payload = {
      url: this.getUrl(`/api/v1/users/${userId}/credit_cards/${id}`),
      method: 'DELETE'
    }

    return this.authenticatedFetchWrap(payload)
  }

  /**
   * @function deleteCreditCard
   * @param {object} payload - The creditCard payload
   * @param {number|string} [payload.userId='me'] - userid to assign this echeck
   * @param {number} payload.id - creditCard id
   * @example
   *
   * deleteCreditCard({
   *   id: 1234
   * })
   */

  prototype.deleteCreditCard = function (payload) {
    const {
      userId,
      id
    } = payload

    const finalPayload = {
      userId: this.normalizeUserId(userId),
      id
    }

    const raw = ifPromise(finalPayload, () => this._deleteCreditCard(finalPayload))
    return raw
      .catch(error => this.onError('deleteCreditCard', error))
  }

  prototype._getCreditCard = function ({ userId, id }) {
    const payload = {
      url: this.getUrl(`/api/v1/users/${userId}/credit_cards/${id}`),
      method: 'GET'
    }

    return this.authenticatedFetchWrap(payload)
  }

  prototype.getCreditCard = function (payload) {
    const raw = ifPromise(payload, () => this._getCreditCard(payload))
    return raw
      .then(res => Promise.resolve(this.normalizeAndCamelize(res)))
      .catch(error => {
        Promise.reject(Error('userError', error))
      })
  }

  prototype._setDefaultCreditCard = function ({ userId, id }) {
    const payload = {
      url: this.getUrl(`/api/v1/users/${userId}/credit_cards/${id}/set_default`),
      method: 'PUT'
    }

    return this.authenticatedFetchWrap(payload)
  }

  /**
   * @function setDefaultCreditCard
   * @param {object} payload - The payload
   * @param {string} [payload.userId='me'] - user id
   * @param {number} payload.id - credit card id
   * @returns {void}
   * @example
   *
   * setDefaultCreditCard({
   *   id: 123
   * })
   */

  prototype.setDefaultCreditCard = function (payload) {
    const finalPayload = {
      id: payload.id,
      userId: this.normalizeUserId(payload.userId)
    }
    const raw = ifPromise(payload, () => this._setDefaultCreditCard(finalPayload))
    return raw
      .catch(error => this.onError('setDefaultCreditCard', error))
  }
}

export default ZEventsApiEvent