const crypto = require('crypto')

const { API_SECRET } = require('./app.config')

const sendError = (res, name = 'InternalServerError', messages = ['UnknownError'], status = 500) => {
  res.status(status).json({
    success: false,
    error: {
      name,
      messages,
      code: status,
    },
  })
}

const authenticate = (req, res, next) => {
  const reqSignature = req.headers['x-algotrading-signature']
  const ts = req.headers['x-algotrading-timestamp']

  if (reqSignature && ts) {
    const signature = crypto.createHmac('sha256', `${API_SECRET}`).update(ts).digest('hex')

    if (reqSignature === signature) {
      next()
      return
    }
  }

  next({
    isAuth: true,
  })
}

const notFound = (req, res, next) => {
  const error = {
    notFound: true,
    messages: [`Page '${req.originalUrl} not found'`],
  }
  next(error)
}

/* eslint-disable no-unused-vars */
const errorHandler = (err, req, res, next) => {
  if (err && typeof err === 'object') {
    // Joi validation
    if (err.isJoi) {
      const { name, details } = err
      const messages = details.map(({ message }) => message)

      sendError(res, name, messages, 400)
      return
    }

    // Unauthorized
    if (err.isAuth) {
      sendError(res, 'AuthenticationError', ['Wrong authentication credentials'], 401)
      return
    }

    if (err.notFound) {
      sendError(res, 'NotFoundError', err.messages, 404)
      return
    }

    // Mongo duplicate
    if (err.code === 11000) {
      sendError(res, 'DuplicateError', ['Document with specified \'_id\' already exists'], 409)
      return
    }

    if (err.status && err.messages && err.name) {
      sendError(res, err.name, err.messages, err.status)
      return
    }
  }

  sendError(res)
}

module.exports = {
  authenticate,
  notFound,
  errorHandler,
}
