'use strict';

/*
  The @serverless/cloud package is how you define your infrastructure from code.
*/
const serverless = require('@serverless/cloud'); // eslint-disable-line

/*
  The @serverless/data package gives easy access to Serverless Data.
  It is also included by default in the cloud runtime.
  So you don't have to include it in package.json.
*/
const { data } = require('@serverless/data'); // eslint-disable-line

const express = require('express');

const app = serverless();

// define your express api, middlewares and routes like you've always done
const api = express();

api.use(express.json());

/*
  Home Page
*/
api.get('/', async (req, res, next) => {
  try {
    // during dev mode, all logs like this are streamed in real time to your terminal
    console.log('This is a streaming log from your live serverless application');

    // you can easily send html responses with express
    const html = `
<h1>Welcome to Serverless Cloud</h1>

<p>
You've successfully deployed a data-driven serverless app to Serverless Cloud. You can get back to the terminal to see live logs as requests come in.
</p>

<p>
visit the /set/foo/bar route to set a new item into Serverless Data.
</p>

<p>
visit the /get/foo/ route to get the item you just set to Serverless Data.
</p>
`;

    res.send(html);
  } catch (e) {
    next(e);
  }
});

/*
  Sets data to Serverless Data with the provided key & value
*/
api.get('/set/:key/:value', async (req, res, next) => {
  try {
    const {
      params: { key, value },
    } = req;

    if (!key || !value) {
      throw new Error('Missing "key" or "value" params.');
    }

    console.log(`Setting "${key}"`);

    // just run the .set method to set an item to Serverless Data
    await data.set(key, value);

    res.send(`Successfully set key "${key}" with value "${value}"`);
  } catch (e) {
    next(e);
  }
});

/*
  Fetches data from Serverless Data with the provided key
*/
api.get('/get/:key', async (req, res, next) => {
  try {
    const {
      params: { key },
    } = req;

    if (!key) {
      throw new Error('Missing "key" param.');
    }

    console.log(`Getting "${key}"`);

    // just run the .get method to get an item by key
    const value = await data.get(key);

    res.send(value);
  } catch (e) {
    next(e);
  }
});

/*
  Error handler
*/
// eslint-disable-next-line
api.use((err, req, res, next) => {
  // errors are also streamed live to your terminal in dev mode.
  console.error(err.stack);

  if (!err.statusCode) {
    err.statusCode = 500;
  }

  const error = {
    name: err.name,
    statusCode: err.statusCode,
    message: err.message,
  };

  res.status(err.statusCode).json(error);
});

// Connect your API to HTTP events
app.http(api);
