const log = require("../utils/logs.utils"); // Log Helper
const db = require("../services/dbAccess.services");
const os = require("os");
const vers = require("../configs/version.configs");

async function buildJson() {
  let json = {};
  json.count = {};
  // Async call all db queries
  const counters = db.query("meta", { target: "counters" });
  const versions = db.query("meta", { target: "versions" });
  const userCount = db.colCount("users");
  const regCount = db.colCount("registrations");
  const pisCount = db.colCount("pis");
  const corpusCount = db.colCount("corpus");
  const stationsCount = db.colCount("stations");
  const timetableCount = db.colCount("timetable");

  // Insert data
  json.mode = process.env.NODE_ENV;
  json.verBkend = vers.app;
  json.verApi = vers.api;
  json.host = os.hostname();
  // Await and insert async calls
  json.dat = await counters;
  json.ver = await versions;
  json.count.users = await userCount;
  json.count.reg = await regCount;
  json.count.pis = await pisCount;
  json.count.corpus = await corpusCount;
  json.count.stations = await stationsCount;
  json.count.timetable = await timetableCount;
  return json;
}

async function hits() {
  log.out("statsServices.hits: Statistics Requested", "info");
  const out = await buildJson();
  log.out(`statsServices.hits: Sending Data: ${JSON.stringify(out)}`, "info");
  return out;
}

async function getVersions() {
  log.out("statsServices.getVersions: Fetching versions", "info");
  const dbMan = await db.query("versions", { target: "dbmanager" });
  const mqClt = await db.query("versions", { target: "mq-client" });
  const data = {
    backend: vers.app,
    "db-manager": dbMan[0]?.["version"] || "",
    "mq-client": mqClt[0]?.["version"] || "",
  };
  return data;
}

async function statistics() {
  log.out("statsServices.statistics: Fetching statistics", "info");

  const countersPromise = db.query("meta", { target: "counters" });
  const timetablePromise = db.query("meta", { target: "timetable" });
  const pisPromise = db.query("meta", { target: "pis" });
  const corpusPromise = db.query("meta", { target: "corpus" });
  const reasonCodesPromise = db.query("meta", { target: "reasonCodes" });

  const lengthUsersPromise = db.colCount("users");
  const lengthRegistrationsPromise = db.colCount("registrations");
  const lengthCorpusPromise = db.colCount("corpus");
  const lengthStationsPromise = db.colCount("stations");
  const lengthPisPromise = db.colCount("pis");
  const lengthTimetablePromise = db.colCount("timetable");
  const lengthReasonCodesPromise = db.colCount("reasonCodes");

  const [
    counters,
    timetable,
    pis,
    corpus,
    reasonCodes,
    lengthUsers,
    lengthRegistrations,
    lengthCorpus,
    lengthStations,
    lengthPis,
    lengthTimetable,
    lengthReasonCodes,
  ] = await Promise.all([
    countersPromise,
    timetablePromise,
    pisPromise,
    corpusPromise,
    reasonCodesPromise,
    lengthUsersPromise,
    lengthRegistrationsPromise,
    lengthCorpusPromise,
    lengthStationsPromise,
    lengthPisPromise,
    lengthTimetablePromise,
    lengthReasonCodesPromise,
  ]);

  return {
    hostname: os.hostname() || "Unknown",
    runtimeMode: process.env.NODE_ENV || "Unknown",
    reset: counters[0]["since"],
    updateTimes: {
      timetable: timetable[0]["updated"],
      pis: pis[0]["updated"],
      corpus: corpus[0]["updated"],
      reasonCodes: reasonCodes[0]["updated"],
    },
    requestCounts: {
      ldbws_api: counters[0]["ldbws"] || 0,
      lsbsvws_api: counters[0]["ldbsvws"] || 0,
      corpus_api: counters[0]["corpus_api"] || 0,
      timetable_db: counters[0]["timetable"] || 0,
      pis_db: counters[0]["pis"] || 0,
      corpus_db: counters[0]["corpus"] || 0,
      stations_db: counters[0]["stations"] || 0,
    },
    dbLengths: {
      users: lengthUsers,
      registrations: lengthRegistrations,
      corpus: lengthCorpus,
      stations: lengthStations,
      pis: lengthPis,
      timetable: lengthTimetable,
      reasonCodes: lengthReasonCodes,
    },
  };
}

module.exports = {
  hits,
  statistics,
  getVersions,
};
