const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

require("dotenv").config();
const port = process.env.PORT || 3052;
const ONE_MINUTE_MS = 60 * 1000;

const { checkAuthKeys, checkAdminAuthKey } = require("./modules/auth");

const app = express();
app.use(cors());
app.use(bodyParser.json({ limit: "250mb" }));
const jsonParser = bodyParser.json();
// app.use(express.static("public"));

// Routes

app.post( "/:client/add-data", jsonParser, checkAuth, require("./modules/add-data") );
app.post( "/:client/delete-records", checkAuth, require("./modules/delete-records") );
app.get( "/:client/get-all-data/:tableName", checkAuth, require("./modules/get-all-data") );
app.get( "/:client/get-gz-file/:tableName", checkAuth, require("./modules/get-gz-file") );
app.get( "/:client/get-data-page/:tableName/:page", checkAuth, require("./modules/get-data-page") );
app.get( "/:client/get-data-within-range-created/:tableName/:from/:to", checkAuth, require("./modules/get-data-within-range-created") );
app.get( "/:client/get-data-within-range-updated/:tableName/:from/:to", checkAuth, require("./modules/get-data-within-range-updated") );
app.delete( "/:client/delete-table/:tableName", checkAuth, require("./modules/delete-table") );

// Admin routes. (Admin can also use routes above for adding/viewing api keys).
app.get("/admin/list-tables", checkIfAdmin, require("./modules/list-tables"));
app.post("/admin/add-table", checkIfAdmin, require("./modules/add-table"));

// Leave these as the are for now (2024-08-13). Chang test before enabling:
// app.get('/get-data-within-range/:tableName/:from/:to', checkAuth, require('./modules/get-data-within-range')); // Problem: Timestamp is now US date. Was epoch.
// app.put('/update-data/:id', jsonParser, checkAuth, require('./modules/update-data'));
// app.get('/get-data/:tableName/:id', checkAuth, require('./modules/get-data'));
// app.get('/get-data-within-dateTime-range/:tableName/:from/:to', checkAuth, require('./modules/getDataWithinRange'));
// app.get('/get-records-count/:tableName', checkAuth, require('./modules/getRecordsCount'));
// app.get('/search/:tableName/:fieldName/:value', checkAuth, require('./modules/search-data'));
// app.get('/transactionsByPostDate', checkAuth, require('./modules/filter-transactions-postDate')); // Only osi.

app.use((req, res) => {
  res.status(404).json({ message: "Not found. Incorrect endpoint." });
});

const server = app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

server.requestTimeout = ONE_MINUTE_MS;
server.headersTimeout = ONE_MINUTE_MS + 5000;
server.keepAliveTimeout = ONE_MINUTE_MS;

// Middleware function to check the Bearer token for create, update, delete operations.
async function checkAuth(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return res.status(401).json({ message: "Unauthorized" });
  }
  const apiKey = authHeader.slice(7);
  const client = req.params.client;
  let tableName;

  if (
    req["url"].includes("add-data") ||
    req["url"].includes("delete-records")
  ) {
    tableName = req.body.tableName;
  } else {
    tableName = req.params.tableName;
  }

  if (!(await checkAuthKeys(client, apiKey, tableName))) {
    return res.status(401).json({ message: "Unauthorized" });
  }
  // Key is valid, so continue processing the request
  next();
}

// Middleware function to check if request is from admin.
async function checkIfAdmin(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return res.status(401).json({ message: "Unauthorized" });
  }
  const apiKey = authHeader.slice(7);

  if (!(await checkAdminAuthKey(apiKey))) {
    return res.status(401).json({ message: "Unauthorized" });
  }
  // Key is valid, so continue processing the request
  next();
}
