const env = require("../environment")
const { Headers } = require("../../constants")
const cls = require("./FunctionContext")

exports.DEFAULT_TENANT_ID = "default"

exports.isDefaultTenant = () => {
  return exports.getTenantId() === exports.DEFAULT_TENANT_ID
}

exports.isMultiTenant = () => {
  return env.MULTI_TENANCY
}

const TENANT_ID = "tenantId"

// used for automations, API endpoints should always be in context already
exports.doInTenant = (tenantId, task) => {
  return cls.run(() => {
    // set the tenant id
    cls.setOnContext(TENANT_ID, tenantId)

    // invoke the task
    return task()
  })
}

exports.updateTenantId = tenantId => {
  cls.setOnContext(TENANT_ID, tenantId)
}

exports.setTenantId = (
  ctx,
  opts = { allowQs: false, allowNoTenant: false }
) => {
  let tenantId
  // exit early if not multi-tenant
  if (!exports.isMultiTenant()) {
    cls.setOnContext(TENANT_ID, this.DEFAULT_TENANT_ID)
    return
  }

  const allowQs = opts && opts.allowQs
  const allowNoTenant = opts && opts.allowNoTenant
  const header = ctx.request.headers[Headers.TENANT_ID]
  const user = ctx.user || {}
  if (allowQs) {
    const query = ctx.request.query || {}
    tenantId = query.tenantId
  }
  // override query string (if allowed) by user, or header
  // URL params cannot be used in a middleware, as they are
  // processed later in the chain
  tenantId = user.tenantId || header || tenantId

  if (!tenantId && !allowNoTenant) {
    ctx.throw(403, "Tenant id not set")
  }
  // check tenant ID just incase no tenant was allowed
  if (tenantId) {
    cls.setOnContext(TENANT_ID, tenantId)
  }
}

exports.isTenantIdSet = () => {
  const tenantId = cls.getFromContext(TENANT_ID)
  return !!tenantId
}

exports.getTenantId = () => {
  if (!exports.isMultiTenant()) {
    return exports.DEFAULT_TENANT_ID
  }
  const tenantId = cls.getFromContext(TENANT_ID)
  if (!tenantId) {
    throw Error("Tenant id not found")
  }
  return tenantId
}
