const express = require('express')
const app = express()
const port = 3001
const crypto = require('crypto')
const base64 = require('base-64')
const slack = require('../../slack')
const { game: { users }, getUser, fuzzyMatcher } = require('./utils')

const apiGetUserId = hash => {
  return Object.entries(users)
    .filter(([id, user]) => user.pwHash === hash)
    .map(([id, user]) => id)[0]
}

const makeHash = pw =>
  crypto.createHash('md5')
    .update(pw)
    .digest('hex')

const illegalCommands = ['!', '!b']
const lastCalls = {}
const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
  if (illegalCommands.find(command => commandNames.includes(command))) {
    commandNames.forEach(name =>
      app.get('/' + name.replace(/!/gi, ''), async (req, res) => res.send('Command is illegal over the web api.'))
    )
    return
  }
  const route = async (req, res) => {
    const say = async msg => res.send(msg + '\n')
    try {
      const words = ['', ...Object.keys(req.query)]
      const [commandName, ...args] = words
      console.log('INCOMING API CALL:', commandName, words)
      const encoded = req.header('Authorization').substring(5)
      const decoded = base64.decode(encoded).substring(1)
      const event = {
        user: apiGetUserId(makeHash(decoded))
      }
      if (!event.user) {
        res.status(400)
        res.send(
          'User does not exist, or does not have a password.\n' +
          'See \'!setpw help\' for assistance.'
        )
        console.log('  bad password')
        return
      }
      const lastCall = lastCalls[event.user] || 0
      const secondsBetweenCalls = 30
      const currentTime = Math.floor(new Date().getTime() / 1000)
      if (lastCall + secondsBetweenCalls > currentTime) {
        res.status(400)
        res.send(`Must have at least ${secondsBetweenCalls}s between api calls`)
        console.log('  rate limited')
        return
      }
      console.log(`  went through for ${slack.users[event.user]}`)
      lastCalls[event.user] = currentTime

      const user = getUser(event.user)
      const haunted = false
      //await action({ event, say, words, args, commandName })
      const canUse = await condition({ event, say, words, commandName, args, user, userId: event.user, isAdmin: event.user.includes(slack.users.Admin) })
      if (!canUse) {
        await say(`Command '${words[0]}' not found`)
        return
      }
      await action({ event, say, trueSay: say, words, args, commandName, user, userId: event.user, haunted })
    } catch (e) {
      console.error('route error', e)
      await say(`Routing error. Make sure you've set up API access with the !setpw command in slack!\n` +
        'Then you can use calls like `curl -u ":yourpw" \'http://10.3.0.48:3001/stonks\'`')
    }
  }
  commandNames.forEach(name =>
    app.get('/' + name.replace(/!/gi, ''), route)
  )
}

module.exports = {
  addCommand,
  makeHash,
  launch: () => app.listen(port, () => {
    console.log(`Express listening on port ${port}`)
  })
}
