// Parse and return an LDB Request

const ldb = require("ldbs-json");
const util = require("../utils/ldb.utils");
const san = require("../utils/sanitizer.utils");
const db = require("../services/dbAccess.services");

import { logger } from "../utils/logger.utils";

import { transform as staffStationTransform } from "../utils/translators/ldb/staffStation";
import { msgCodes } from "../configs/errorCodes.configs";

const ldbKey = process.env.OWL_LDB_KEY;
const ldbsvKey = process.env.OWL_LDB_SVKEY;

async function get(id, staff = false) {
  const cleanId = san.cleanApiEndpointTxt(id);
  const obj = await util.checkCrs(cleanId);
  try {
    const crs = obj[0]["3ALPHA"];
    logger.debug(`ldbService.get: Determined CRS for lookup to be: ${crs}`)
    if (staff) {
      const data = arrDepBoardStaff(crs);
      db.increment("ldbsvws");
      return await data;
    } else {
      const data = arrDepBoard(crs);
      db.increment("ldbws");
      return await data;
    }
  } catch (err) {
    logger.error(err, "ldbService.get: Error, Unable to find CRS")
    return {
      obStatus: "LOC_NOT_FOUND",
      obMsg: "UNABLE TO FIND MESSAGE",
    };
  }
}

async function arrDepBoard(CRS) {
  logger.trace(`ldbService.arrDepBoard: Trying to fetch board for ${CRS}`)
  try {
    const options = {
      numRows: 10,
      crs: CRS.toUpperCase(),
    };
    const api = new ldb(ldbKey, false);
    let d = await api.call("GetArrDepBoardWithDetails", options, false, false);
    return await util.cleanData(d);
  } catch (err) {
    logger.error(err, "ldbService.arrDepBoard: Lookup Failed")
    return {
      GetStationBoardResult: "not available",
      Reason: `The CRS code ${CRS} is not valid`,
    };
  }
}

async function arrDepBoardStaff(CRS) {
  logger.debug(`ldbService.arrDepBoardStaff: Try to fetch board for ${CRS}`)
  try {
    const options = {
      numRows: 40,
      crs: CRS.toUpperCase(),
      getNonPassengerServices: true,
      time: await getDateTimeString(new Date()),
      timeWindow: 120,
      services: "PBS",
    };
    const api = new ldb(ldbsvKey, true);
    console.time(`Fetch Staff LDB for ${CRS.toUpperCase()}`);
    const result = await api.call(
      "GetArrivalDepartureBoardByCRS",
      options,
      false,
      false
    );
    console.log("\n\n\nORIGINAL DATA")
    console.log("\n" + JSON.stringify(result) + "\n\n\n")
    console.timeEnd(`Fetch Staff LDB for ${CRS.toUpperCase()}`);
    try {
      const _staffLdb = staffStationTransform(result);
      logger.debug("StaffLDB Transformed")
      logger.trace(_staffLdb, "StaffLDB Transformed")
      return {
        obStatus: "OK",
        obMsg: "OK",
        data: _staffLdb,
      };
    } catch (err) {
      logger.error(err, "Transformation Error")
    }
    return result;
  } catch (err) {
    logger.error(err, "ldbService.arrDepBoardStaff error")
    return {
      GetStationBoardResult: "not available",
      Reason: `The CRS code ${CRS} is not valid`,
    };
  }
}

async function getServiceByRID(rid) {
  logger.debug(`ldbService.getServiceByRID: Finding RID: ${rid}`);
  try {
    const options = {
      rid: String(rid),
    };
    const api = new ldb(ldbsvKey, true);
    return await api.call("GetServiceDetailsByRID", options, false, false);
  } catch (err) {
    logger.error(err, `ldbService.queryService`);
  }
}

async function getServicesByOther(id) {
  logger.debug(`ldbService.getServiceByOther: Finding services: ${id}`);
  try {
    const options = {
      serviceID: id,
      sdd: getDateString(new Date()),
    };
    const api = new ldb(ldbsvKey, true);
    return await api.call("QueryServices", options, false, false);
  } catch (err) {
    logger.error(err, "ldbService.getServiceByOther")
    return false;
  }
}

async function getReasonCodeList() {
  logger.debug("ldbService.getReasonCodeList: Fetching reason code list")
  try {
    const dbFilter = {};
    return await db.query("reasonCodes", dbFilter, false);
  } catch (err) {
    logger.error(err, "ldbService.getReasonCodeList")
  }
}

async function getReasonCode(code) {
  logger.debug(`ldbService.getReasonCode: Fetching reason code ${code}`);
  try {
    const dbFilter = {
      code: code,
    };
    return await db.query("reasonCodes", dbFilter, false);
  } catch (err) {
    logger.error(err, "ldbService.getReasonCode")
  }
}

async function getDateTimeString(date) {
  const year = date.getFullYear(),
    month = String(date.getMonth() + 1).padStart(2, "0"),
    day = String(date.getDate()).padStart(2, "0"),
    hour = String(date.getHours()).padStart(2, "0"),
    minute = String(date.getMinutes()).padStart(2, "0"),
    second = String(date.getSeconds()).padStart(2, "0");
  const format = `${year}-${month}-${day}T${hour}:${minute}:${second}`;
  return format;
}

async function getDateString(date) {
  const year = date.getFullYear(),
    month = String(date.getMonth() + 1).padStart(2, "0"),
    day = String(date.getDate()).padStart(2, "0");
  const format = `${year}-${month}-${day}`;
  return format;
}

module.exports = {
  get,
  getServiceByRID,
  getServicesByOther,
  getReasonCodeList,
  getReasonCode,
};
