/*
 * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors.
 * SPDX-License-Identifier: MIT
 */

import vm = require('vm')
import { Request, Response, NextFunction } from 'express'

const utils = require('../lib/utils')
const security = require('../lib/insecurity')
const safeEval = require('notevil')
const challenges = require('../data/datacache').challenges

module.exports = function b2bOrder () {
  return ({ body }: Request, res: Response, next: NextFunction) => {
    if (!utils.disableOnContainerEnv()) {
      const orderLinesData = body.orderLinesData || ''
      try {
        const sandbox = { safeEval, orderLinesData }
        vm.createContext(sandbox)
        
        // ruleid: express-detect-notevil-usage
        vm.runInContext("safeEval(orderLinesData)", sandbox, { timeout: 2000 })
        // ruleid: express-detect-notevil-usage
        safeEval(orderLinesData)
        // ok
        vm.runInContext("safeEval('orderLinesData')", sandbox, { timeout: 2000 }) // ignore hardcoded strings in semgrep
        // ok
        safeEval('orderLinesData')
        res.json({ cid: body.cid, orderNo: uniqueOrderNumber(), paymentDue: dateTwoWeeksFromNow() })
      } catch (err) {
        if (err.message?.match(/Script execution timed out.*/)) {
          utils.solveIf(challenges.rceOccupyChallenge, () => { return true })
          res.status(503)
          next(new Error('Sorry, we are temporarily not available! Please try again later.'))
        } else {
          utils.solveIf(challenges.rceChallenge, () => { return err.message === 'Infinite loop detected - reached max iterations' })
          next(err)
        }
      }
    } else {
      res.json({ cid: body.cid, orderNo: uniqueOrderNumber(), paymentDue: dateTwoWeeksFromNow() })
    }
  }

  function uniqueOrderNumber () {
    return security.hash(new Date() + '_B2B')
  }

  function dateTwoWeeksFromNow () {
    return new Date(new Date().getTime() + (14 * 24 * 60 * 60 * 1000)).toISOString()
  }
}
