text: const fs = require('fs')
  const path = require('path')
  const express = require('express')
  const https = require('https')
  const serveStatic = require('serve-static')
  const cors = require('cors')
  const helmet = require('helmet')
  const cookieParser = require('cookie-parser')
  const { ApolloServer, AuthenticationError } = require('apollo-server-express')
  const _ = require('lodash/fp')
  
  const T = require('../time')
  const options = require('../options')
  
  const login = require('./login')
  const { typeDefs, resolvers } = require('./graphql/schema')
  
  const devMode = require('minimist')(process.argv.slice(2)).dev
  const NEVER = new Date(Date.now() + 100 * T.years)
  const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
  const frontCameraBasedir = _.get('frontCameraDir', options)
  
  const hostname = options.hostname
  if (!hostname) {
    console.error('Error: no hostname specified.')
    process.exit(1)
  }
  
  const app = express()
  app.use(helmet({ noCache: true }))
  app.use(cookieParser())
  app.use(express.static(path.resolve(__dirname, '..', '..', 'public')))
  
  const apolloServer = new ApolloServer({
    typeDefs,
    resolvers,
    playground: false,
    introspection: false,
    formatError: error => {
      console.log(error)
      return error
    },
    context: async ({ req }) => {
      const token = req.cookies && req.cookies.token
  
      const success = await login.authenticate(token)
      if (!success) throw new AuthenticationError('Authentication failed')
    }
  })
  
  apolloServer.applyMiddleware({
    app,
    cors: {
      credentials: true,
      origin: devMode && 'https://localhost:3000'
    }
  })
  
  // cors on app for /api/register endpoint.
  app.use(cors({ credentials: true, origin: devMode && 'https://localhost:3000' }))
  
  app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, { index: false }))
  app.use('/front-camera-photo', serveStatic(frontCameraBasedir, { index: false }))
  
  app.get('/api/register', (req, res, next) => {
    const otp = req.query.otp
  
    if (!otp) return next()
  
    return login.register(otp)
      .then(r => {
        if (r.expired) return res.status(401).send('OTP expired, generate new registration link')
  
        // Maybe user is using old registration key, attempt to authenticate
        if (!r.success) return next()
  
        const cookieOpts = {
          httpOnly: true,
          secure: true,
          domain: hostname,
          sameSite: true,
          expires: NEVER
        }
  
        const token = r.token
        req.token = token
        res.cookie('token', token, cookieOpts)
        res.sendStatus(200)
      })
  })
  
  // Everything not on graphql or api/register is redirected to the front-end
  app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '..', '..', 'public', 'index.html')))
  
  const certOptions = {
    key: fs.readFileSync(options.keyPath),
    cert: fs.readFileSync(options.certPath)
  }
  
  function run () {
    const serverPort = devMode ? 8070 : 443
  
    const serverLog = `lamassu-admin-server listening on port ${serverPort}`
  
    const webServer = https.createServer(certOptions, app)
    webServer.listen(serverPort, () => console.log(serverLog))
  }
  
  module.exports = { run }
  