Source: middleware/organisations.middleware.js

import { logPageError } from './common.middleware.js'
import { fetchMany, onlyIf, renderTemplate } from './middleware.builders.js'
import { setOrganisationList, getOrganisationList } from '../utils/redisLoader.js'
import logger from '../utils/logger.js'
import config from '../../config/index.js'

const fetchOrganisations = fetchMany({
  query: ({ req, params }) => `
    SELECT DISTINCT
      p.organisation,
      o.name
    FROM
      provision p
      LEFT JOIN organisation o ON p.organisation = o.organisation
    WHERE
      (
        p.organisation LIKE 'local-authority:%'
        OR p.organisation LIKE 'national-park-authority:%'
        OR p.organisation LIKE 'development-corporation:%'
      )
      AND (
        p.end_date IS NULL
        OR p.end_date = ''
        OR p.end_date >= CURRENT_TIMESTAMP
      )
      AND (
        p.provision_reason IN (${config.provisionReasons.map(reason => `'${reason}'`).join(', ')})
      );
  `,
  result: 'organisations'
})

// Try to load organisations from Redis cache, if available to avoid LEFT JOIN Operation
export const loadOrganisations = async (req, res, next) => {
  try {
    const cached = await getOrganisationList()
    if (cached) {
      req.organisations = cached
      req.cached = true
    }
  } catch (e) {
    logger.warn('Error loading organisations from cache', e)
  }
  next()
}

export const saveOrganisations = async (req, res, next) => {
  if (req.organisations) {
    try {
      await setOrganisationList(req.organisations)
    } catch (e) {
      logger.warn('Error setting organisations cache', e)
    }
  }
  next()
}

/**
 * Middleware. Updates req with `templateParams`.
 *
 * @param {Object} req - Express request object
 * @param {Array<Object>} req.organisations - Array of organisation objects
 * @param {Object} res - Express response object
 * @param {Function} next - Express next function
 * @returns {void}
 */
export const prepareGetOrganisationsTemplateParams = (req, res, next) => {
  const sortedResults = req.organisations.sort((a, b) => {
    return a.name.localeCompare(b.name)
  })

  const alphabetisedOrgs = sortedResults.reduce((acc, current) => {
    const firstLetter = current.name.charAt(0).toUpperCase()
    acc[firstLetter] = acc[firstLetter] || []
    acc[firstLetter].push(current)
    return acc
  }, {})

  req.templateParams = { alphabetisedOrgs }

  next()
}

export const getOrganisations = renderTemplate({
  templateParams: (req) => req.templateParams,
  template: 'organisations/find.html',
  handlerName: 'getOrganisations'
})

export default [
  loadOrganisations,
  onlyIf(req => !req.cached, fetchOrganisations),
  onlyIf(req => !req.cached, saveOrganisations),
  prepareGetOrganisationsTemplateParams,
  getOrganisations,
  logPageError
]