// Ignore paths for logging, metrics and docs
// Fast, minimalist web framework for node.
import express from 'express'

// Helmet helps you secure your Express app by setting various HTTP headers
import helmet from 'helmet'

// Fastest HTTP logger for Node.js in town
import { logger } from './logger.js'
import pinoHttp from 'pino-http'
// Readiness and liveness checks middleware
import health from '@cloudnative/health-connect'

// Prometheus middleware for standard api metrics
import promBundle from 'express-prom-bundle'

// Swagger UI for api-docs
import swaggerUi from 'swagger-ui-express'
import yaml from 'js-yaml'
import fs from 'fs'
import { getDependencies, getOxManifests } from './manifests.js'

const ignorePaths = ['/ready', '/healthy']
const httpLogger = pinoHttp({ logger, autoLogging: { ignorePaths } })
const swaggerDocument = yaml.load(fs.readFileSync('./src/swagger.yaml', 'utf8'))
const bypass = (request) => ignorePaths.includes(request.path)
const metricsMiddleware = promBundle({ bypass })

export function createApp () {
  // The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.

  const app = express()

  const healthCheck = new health.HealthChecker()

  // Application-level middleware
  app.use(httpLogger)
  app.use(helmet())
  app.use('/healthy', health.LivenessEndpoint(healthCheck))
  app.use('/ready', health.ReadinessEndpoint(healthCheck))
  app.use(metricsMiddleware)
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
  app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
  app.timeout = 30000

  app.get('/api/manifest.json', async (req, res, next) => {
    try {
      res.json(await getOxManifests())
    } catch (err) {
      next(err)
    }
  })

  app.get('/api/deps.json', async (req, res, next) => {
    try {
      res.json(await getDependencies())
    } catch (err) {
      next(err)
    }
  })

  app.use(function (err, req, res, next) {
    logger.error(err)
    res.status(500).end()
  })

  return app
}