import { createHash } from 'crypto'

import Router from '@koa/router'
import IORedis from 'ioredis'
import IORedisMock from 'ioredis-mock'
import { koaBody } from 'koa-body'

const Redis = IORedis.default
const RedisMock = IORedisMock.default

// cache expires in 24 hours (in seconds)
const CACHE_EXPIRE = 24 * 60 * 60

const redis =
	process.env.NODE_ENV === 'production' && process.env.SCALINGO_REDIS_URL
		? new Redis(process.env.SCALINGO_REDIS_URL, {
				enableOfflineQueue: false,
				keyPrefix: 'cache',
		  })
		: new RedisMock()

export const redisCacheMiddleware = () => {
	const router = new Router()

	router.post('/evaluate', koaBody(), async (ctx, next) => {
		if (!redis || !ctx.request.body) {
			await next()

			return
		}

		const cacheKey = createHash('sha1')
			.update(JSON.stringify(ctx.request.body))
			.digest('base64')

		const cachedResponse = await redis.get(cacheKey)
		if (cachedResponse) {
			ctx.body = JSON.parse(cachedResponse) as unknown

			return
		}

		await next()

		if (ctx.status === 200) {
			const responseCachedAt = Date.now()
			const cacheExpiresAt = responseCachedAt + CACHE_EXPIRE * 1000
			await redis.set(
				cacheKey,
				JSON.stringify({ responseCachedAt, cacheExpiresAt, ...ctx.body }),
				'EX',
				CACHE_EXPIRE
			)
		}
	})

	return router.routes()
}