const logger = require('logger-sharelatex')
const metrics = require('metrics-sharelatex')

class RequestLogger {
  constructor() {
    this._logInfo = {}
    this._logMessage = 'http request'
  }

  addFields(fields) {
    Object.assign(this._logInfo, fields)
  }

  setMessage(message) {
    this._logMessage = message
  }

  static errorHandler(err, req, res, next) {
    req.requestLogger.addFields({ error: err })
    res
      .send(err.message)
      .status(500)
      .end()
  }

  static middleware(req, res, next) {
    const startTime = new Date()
    req.requestLogger = new RequestLogger()

    // override the 'end' method to log and record metrics
    const end = res.end
    res.end = function() {
      // apply the standard request 'end' method before logging and metrics
      end.apply(this, arguments)

      const responseTime = new Date() - startTime

      const routePath = req.route && req.route.path.toString()

      if (routePath) {
        metrics.timing('http_request', responseTime, null, {
          method: req.method,
          status_code: res.statusCode,
          path: routePath
            .replace(/\//g, '_')
            .replace(/:/g, '')
            .slice(1)
        })
      }

      const level = res.statusCode >= 500 ? 'err' : 'log'
      logger[level](
        {
          req: {
            url: req.originalUrl || req.url,
            route: routePath,
            method: req.method,
            referrer: req.headers.referer || req.headers.referrer,
            'remote-addr':
              req.ip ||
              (req.socket && req.socket.remoteAddress) ||
              (req.socket &&
                req.socket.socket &&
                req.socket.socket.remoteAddress),
            'user-agent': req.headers['user-agent'],
            'content-length': req.headers['content-length']
          },
          res: {
            'content-length': res._headers['content-length'],
            statusCode: res.statusCode,
            'response-time': responseTime
          },
          info: req.requestLogger._logInfo
        },
        req.requestLogger._logMessage
      )
    }

    next()
  }
}

module.exports = RequestLogger
