/* global ubs_message */
const { Session, Repository, DataStore } = require('@unitybase/ub')

ubs_message.entity.addMethod('getCached')
ubs_message.entity.addMethod('selectAll')
ubs_message.on('select:before', addUserFilters)

/**
 * If something changes in ubs_messages from a last call - return a messages.
 *
 * @function getCached
 * @memberOf ubs_message_ns.prototype
 * @memberOfModule @unitybase/ubs
 * @published
 * @param {ubMethodParams} ctx
 * @returns {boolean}
 */
ubs_message.getCached = function (ctx) {
  if (ctx.mParams.version) {
    const expr = 'SELECT MAX(mi_modifyDate) AS "last_number" FROM ubs_message'
    const store = DataStore('ubs_message')
    store.runSQL(expr, {})
    const versionFromDb = store.get('last_number')
    store.freeNative()
    const version = new Date(versionFromDb).getTime()
    const notModified = version === Number(ctx.mParams.version)
    ctx.mParams.version = version
    if (notModified) {
      ctx.mParams.resultData = { notModified: true }
      return true
    }
  }
  ctx.dataStore.run('select', ctx.mParams)
}

/**
 * Select all ubs_messages (ubs_messages.select returns incomplete messages for current user)
 *
 * @function selectAll
 * @memberOf ubs_message_ns.prototype
 * @memberOfModule @unitybase/ubs
 * @published
 * @param {ubMethodParams} ctx
 * @returns {boolean}
 */
ubs_message.selectAll = function (ctx) {
  ctx.mParams.__skipAclRls = true
  ctx.dataStore.run('select', ctx.mParams)
}

ubs_message.skipAclRls = function () {
  return false
}

/**
 * Check if user try fetching own message by ID (to create/modify it)
 *
 * @private
 * @param ctx
 * @returns {boolean}
 */
function isFetchOwnMessage (ctx) {
  const ID = ctx.mParams.ID
  if (ID) {
    return Repository('ubs_message')
      .attrs('mi_owner')
      .misc({ __skipAclRls: true })
      .where('ID', '=', ID)
      .selectScalar() === Session.userID
  }
  return false
}

/**
 * Check if fieldList or whereList contains references to the recipients column
 * @param {object} mParams - The parameters object
 * @param {string[]} [mParams.fieldList=[]] - List of field names to check
 * @param {object} [mParams.whereList={}] - Where conditions to check for recipient restrictions
 * @returns {boolean} True if any field or where condition references a recipient column, false otherwise
 */
function hasRecipientRestriction (mParams) {
  /**
   * Add bracket to fieldName if it is not present
   * @param {string} fName
   * @returns {string}
   */
  function addBracket (fName) {
    return fName[0] === '[' ? fName : '[' + fName + ']'
  }
  const { fieldList = [], whereList = {} } = mParams
  const recipientPrefix = '[recipients.'
  return fieldList.some(field => addBracket(field).startsWith(recipientPrefix)) ||
    Object.values(whereList).some(where => where.expression && addBracket(where.expression).startsWith(recipientPrefix))
}

/**
 * Filter only complete(ready for send) up-to-date messages
 *
 * @private
 * @param {ubMethodParams} ctx
 * @returns {boolean}
 */
function addUserFilters (ctx) {
  const nm = Date.now()
  const mParams = ctx.mParams
  if (App.els('ubs_message', 'insert') || !ctx.externalCall) {
    if (mParams.__skipAclRls || isFetchOwnMessage(ctx)) {
      // user can insert messages so can potentially read all and read one message by ID
      // usually - SysOps role
      mParams.__skipAclRls = true
      return true
    }
  }

  if (!mParams.whereList) {
    mParams.whereList = {}
  }

  if (hasRecipientRestriction(mParams)) {
    mParams.whereList['user' + nm] = {
      expression: '[recipients.userID]',
      condition: 'equal',
      value: Session.userID
    }
    mParams.joinAs = ['user' + nm]
  }

  mParams.whereList['complete' + nm] = {
    expression: '[complete]',
    condition: 'equal',
    value: 1
  }
  mParams.whereList['startDate' + nm] = {
    expression: '[startDate]',
    condition: 'less',
    value: new Date()
  }
  return true
}