const prompt = require("prompts");
const validate = require("uuid").validate;
const uuid = require("uuid");
const ora = require("ora");
const mysql = require("mysql");
const fs = require("fs");

function isFutureDate(value) {
  const d_now = new Date();
  const d_inp = new Date(value);
  return d_now.getTime() <= d_inp.getTime();
}

let jsonConfigGlobal = {
  fontAwesome: undefined,
  mapboxAccessToken: undefined,
  cookieSecret: undefined,
  database: {
    host: undefined,
    user: undefined,
    password: undefined,
    database: undefined,
  },
  env: undefined,
  maint: undefined,
};

// Load config
try {
  const data = fs.readFileSync("../../config/default.json", "utf8");
  jsonConfigGlobal = JSON.parse(data);
} catch (error) {
  console.error(
    "While reading the config an error occured. The error was: " + error
  );
}

const connectionPool = mysql.createPool(jsonConfigGlobal.database);

console.log(
  "                               --[Pointsight API key management]-- "
);
console.log(
  " Welcome to the Pointsight api key manager. THIS SOFTWARE MY ONLY BE USED BY AUTHORIZED PERSONELL. \n \
 This tool enables you to create and manage api keys. Use responsible."
);

// prompt.inject([ 'yes', "" ]);

const questions = [
  {
    type: "confirm",
    name: "value",
    message: "Are you authorized to use this software",
    initial: false,
  },
  {
    type: (prev, values, prompt) => (values.value == true ? "select" : null),
    name: "cmd",
    message: "What do you want to do?",
    choices: [
      { title: "whois", value: "whois" },
      { title: "create", value: "create" },
      { title: "edit", value: "edit" },
      { title: "delete", value: "delete" },
      { title: "quit" },
    ],
  },
  {
    type: (prev, values, prompt) => (prev == "whois" ? "text" : null),
    name: "key",
    message: "Please enter the api key you want to lookup",
    validate: (value) =>
      validate(value) ? true : `Please enter a valid api key`,
  },
  {
    type: (prev, values, prompt) => (values.cmd == "edit" ? "text" : null),
    name: "key",
    message: "Please enter the api key you want to edit",
    validate: (value) =>
      validate(value) ? true : `Please enter a valid api key`,
  },
  {
    type: (prev, values, prompt) => (values.cmd == "delete" ? "text" : null),
    name: "key",
    message: "Please enter the api key you want to delete",
    validate: (value) =>
      validate(value) ? true : `Please enter a valid api key`,
  },
  {
    type: (prev, values, prompt) => (values.cmd == "delete" ? "confirm" : null),
    name: "sure",
    message: (prev, values, prompt) =>
      "Are you sure you want to delete " + prev + "?",
  },
  {
    type: (prev, values, prompt) => (values.cmd == "create" ? "text" : null),
    name: "owner",
    message: "Enter the owner of the apikey",
  },
  {
    type: (prev, values, prompt) => (values.cmd == "create" ? "list" : null),
    name: "hosts",
    message: "Enter all hosts, sperated by a ','",
  },
  {
    type: (prev, values, prompt) => (values.cmd == "create" ? "date" : null),
    name: "expire",
    message: "Enter an expiration date",
    validate: (date) =>
      date < Date.now() ? "Date is not in the future" : true,
  },
];
(async () => {
  const response = await prompt(questions);
  console.log(response);
  if (response.cmd == "whois") {
    const spinner = ora("Initating MySQL Database connection").start();
    connectionPool.getConnection((err, conn) => {
      if (err) {
        throw err;
      }
      spinner.text = "Sending SQL query to server";
      //i do query stuff
      const query = "SELECT * FROM apikeys WHERE apikey=?";
      conn.query(query, [response.key], function (err, result) {
        if (err) throw err;

        if (result.length != 1) {
          spinner.warn("No or too many results have been found");
        } else {
          spinner.succeed("Database requests done.");
        }
        console.log("Found a result: ");
        console.log(" Key: " + result[0].apikey);
        console.log(" Owner: " + result[0].owner);
        console.log(" Hosts: " + result[0].hosts);
        console.log(" Creation date: " + result[0].created);
        console.log(" Expire date: " + result[0].expire);
        console.log(" Has expired: " + !isFutureDate(result[0].expire));
      });

      //i close the connection
      conn.release();
    });
  } else if (response.cmd == "create") {
    const sqlQuery =
      "INSERT INTO `apikeys` (`id`, `apikey`, `owner`, `hosts`, `created`, `expire`) VALUES (NULL, ?, ?, ?, current_timestamp(), ?);";
    const spinner = ora("Initating MySQL Database connection").start();
    connectionPool.getConnection((err, conn) => {
      if (err) {
        throw err;
      }
      spinner.text = "Sending SQL query to server";
      const allHosts = response.hosts;
      let hostString = "[";
      for (eI in allHosts) {
        host = allHosts[eI];
        hostString += '"' + host + '"';
        if (eI < allHosts.length - 1) {
          hostString += ",";
        }
      }
      hostString += "]";

      const myUUID = uuid.v4();
      conn.query(
        sqlQuery,
        [myUUID, response.owner, hostString, response.expire],
        function (err, result) {
          if (err) throw err;
          spinner.succeed("Database request done.");

          console.log(" Created api key `" + myUUID + "`.");
        }
      );
      conn.release();
    });
  } else if (response.cmd == "delete" && response.sure == true) {
    const sqlQuery = "DELETE FROM `apikeys` WHERE `apikey` = ?";
    const spinner = ora("Initating MySQL Database connection").start();

    connectionPool.getConnection((err, conn) => {
      if (err) {
        throw err;
      }
      spinner.text = "Sending SQL query to server";

      conn.query(sqlQuery, [response.key], function (err, result) {
        if (err) throw err;
        spinner.succeed("Database request done.");
      });
      conn.release();
    });
  } else if (response.cmd == "edit") {
    const sqlQuery = "DELETE FROM `apikeys` WHERE `apikey` = ?";
    const spinner = ora("Initating MySQL Database connection").start();

    connectionPool.getConnection((err, conn) => {
      if (err) {
        throw err;
      }
      spinner.text = "Sending SQL query to server";
      const query = "SELECT * FROM apikeys WHERE apikey=?";
      conn.query(query, [response.key], function (err, result) {
        if (err) throw err;

        if (result.length != 1) {
          spinner.warn("No or too many results have been found");
        } else {
          spinner.succeed("Database requests done.");
          console.log(result[0]);
          const histy = JSON.parse(result[0].hosts);
          const editQuestions = [
            {
              type: "text",
              name: "owner",
              initial: result[0].owner,
              message: "Enter the owner of the apikey",
            },
            {
              type: "list",
              name: "hosts",
              initial: histy,
              message: "Enter all hosts, sperated by a ','",
            },
            {
              type: "date",
              name: "expire",
              initial: result[0].expire,
              message: "Enter an expiration date",
              validate: (date) =>
                date < Date.now() ? "Date is not in the future" : true,
            },
          ];
          (async () => {
            const response2 = await prompt(editQuestions);
            console.log(" Key: " + response.key);
            console.log(" Owner: " + response2.owner);
            console.log(" Hosts: " + response2.hosts);
            console.log(" Expire date: " + response2.expire);
            console.log(" Has expired: " + !isFutureDate(response2.expire));
            (async () => {
                const response3 = await prompt({
                  type: "confirm",
                  name: "conf",
                  message: "Is this correct?",
                });
    
                if (response3.conf == true) {
                  const sqlQuery =
                    "UPDATE `apikeys` SET `owner` = ?, `hosts` = ?, `expire` = ? WHERE `apikey` = ?";
                  const spinner = ora(
                    "Initating MySQL Database connection"
                  ).start();
                  connectionPool.getConnection((err, conn) => {
                    if (err) {
                      throw err;
                    }
                    spinner.text = "Sending SQL query to server";
                    const allHosts = response2.hosts;
                    let hostString = "[";
                    for (eI in allHosts) {
                      host = allHosts[eI];
                      hostString += '"' + host + '"';
                      if (eI < allHosts.length - 1) {
                        hostString += ",";
                      }
                    }
                    hostString += "]";
                    conn.query(
                      sqlQuery,
                      [response2.owner, hostString, response2.expire, response.key],
                      function (err, result) {
                        if (err) throw err;
                        spinner.succeed("Database request done.");
                      }
                    );
                    conn.release();
                  });
                }
              })();
          })();
          
        }
      });
      conn.release();
    });
  }
})();
