Source: ZEventsApiCart/ZEventsApiCart.js

const ZEventsApiCart = ({ prototype }) => {
  /**
   * @typedef {object} EventServiceFeeTableRow
   * @property {number} gte - greater-than-or-equal
   * @property {number} lt - less than, if null, this is the max bucket
   * @property {number} fee - per ticket fee for this row
   */

  /**
   * @function getEventServiceFeesSync
   * @returns {EventServiceFeeTableRow[]} - row of service fee table
   * @example
   *
   * getEventServiceFeesSync()
   */
  prototype.getEventServiceFeesSync = function () {
    return ([
      {
        gte: 0,
        lt: 50,
        fee: 1.5
      },
      {
        gte: 50,
        lt: 100,
        fee: 2.5
      },
      {
        gte: 100,
        lt: 250,
        fee: 5.0
      },
      {
        gte: 250,
        lt: 350,
        fee: 6.5
      },
      {
        gte: 350,
        lt: null,
        fee: 7.0
      }
    ])
  }

  /**
   * @function calculateServiceFee
   * @param {object} payload - ticket info payload
   * @param {number} payload.gaTicketPrice - price of a general ticket
   * @param {number} payload.gaTicketCount - how many ga tickets
   * @param {number} payload.vipTicketPrice - price of a vip ticket
   * @param {number} payload.vipTicketCount - how many vip tickets
   * @returns {number} service fee for cart
   * @example
   *
   * calculateServiceFee({
   *  vipTicketCount: 5,
   *  vipTicketPrice: 10,
   *  gaTicketCount: 1,
   *  gaTicketPrice: 3
   * })
   */

  prototype.calculateServiceFee = function (payload) {
    const {
      vipTicketCount,
      vipTicketPrice,
      gaTicketCount,
      gaTicketPrice
    } = payload

    const serviceFeesTable = this.getEventServiceFeesSync()

    let fee = 0
    if (gaTicketCount > 0 && gaTicketPrice > 0) {
      for (const feeBlock of serviceFeesTable) {
        if (gaTicketPrice >= feeBlock.gte) {
          if (feeBlock.lt === null || feeBlock.lt > gaTicketPrice) {
            fee = fee + (gaTicketCount * feeBlock.fee)
          }
        }
      }
    }

    if (vipTicketCount > 0 && vipTicketPrice > 0) {
      for (const feeBlock of serviceFeesTable) {
        if (vipTicketPrice >= feeBlock.gte) {
          if (feeBlock.lt === null || feeBlock.lt > vipTicketPrice) {
            fee = fee + (vipTicketCount * feeBlock.fee)
          }
        }
      }
    }

    return fee
  }

  /**
   * @typedef {object} CartTotals
   * @property {number} serviceFee - total service for for order
   * @property {number} subtotal - (vipTicketCount * vipTicketPrice) + (gaTicketCount * gaTicketPrice)
   * @property {number} tax - tax (currently 0)
   * @property {number} total - overall cart total
   */

  /**
   * @function calculateCartTotals
   * @param {object} payload - ticket info payload
   * @param {number} payload.gaTicketPrice - price of a general ticket
   * @param {number} payload.gaTicketCount - how many ga tickets
   * @param {number} payload.vipTicketPrice - price of a vip ticket
   * @param {number} payload.vipTicketCount - how many vip tickets
   * @returns {CartTotals} cart totals
   * @example
   *
   * calculateCartTotals({
   *  vipTicketCount: 5,
   *  vipTicketPrice: 10,
   *  gaTicketCount: 1,
   *  gaTicketPrice: 3
   * })
   */
  prototype.calculateCartTotals = function (payload) {
    const {
      vipTicketCount,
      vipTicketPrice,
      gaTicketCount,
      gaTicketPrice
    } = payload

    const serviceFee = this.calculateServiceFee(payload)
    const subtotal = (vipTicketCount * vipTicketPrice) + (gaTicketCount * gaTicketPrice)
    const tax = 0
    const total = serviceFee + subtotal + tax

    const ret = {
      serviceFee,
      subtotal,
      tax,
      total
    }

    return ret
  }
}

export default ZEventsApiCart