/**
 * Returns the corresponding component/function/object based on the type of instance.
 * Based on the node env params, return the correct prop.
 * Default is to return the ImEX Prop
 * @typedef {Object} InstanceManagerObject
 * @property { string | object | function } rome  Return this prop if Rome.
 * @property { string | object | function } promanager Return this prop if Rome.
 * @property { string | object | function } imex  Return this prop if Rome.
 */
const { isString, isEmpty } = require("lodash");

/**
 * InstanceManager is a utility function that determines which property to return based on the current instance type.
 * @param param0
 * @param param0.args
 * @param param0.instance
 * @param param0.debug
 * @param param0.executeFunction
 * @param param0.rome
 * @param param0.promanager
 * @param param0.imex
 * @returns {*|null}
 * @constructor
 */
const InstanceManager = ({ args, instance, debug, executeFunction, rome, promanager, imex }) => {
  let propToReturn = null;

  switch (instance || process.env.INSTANCE) {
    case "IMEX":
      propToReturn = imex;
      break;
    case "ROME":
      if (rome === "USE_IMEX") {
        propToReturn = imex;
      } else {
        propToReturn = rome;
      }
      break;
    case "PROMANAGER":
      //Return the rome prop if USE_ROME.
      //If not USE_ROME, we want to default back to the rome prop if it's undefined.
      //If null, we might want to show nothing, so make sure we return null.
      propToReturn = promanager === "USE_ROME" ? rome : promanager !== undefined ? promanager : rome;
      break;
    default:
      propToReturn = imex;
      break;
  }

  if (debug) {
    console.log("InstanceRenderManager Debugger");
    console.log("=========================");
    console.log({ executeFunction, rome, promanager, imex, debug, propToReturn });
    console.log("=========================");
  }

  //Checking to see if we need to default to another one.
  if (propToReturn === "imex") {
    propToReturn = imex;
  }
  if (executeFunction && typeof propToReturn === "function") return propToReturn(...args);
  return propToReturn === undefined ? null : propToReturn;
};

/**
 * Returns the AWS region to be used for the current instance, which is determined by the INSTANCE environment variable.
 * @returns {*}
 * @constructor
 */
const InstanceRegion = () =>
  InstanceManager({
    imex: "ca-central-1",
    rome: "us-east-2"
  });

/**
 * Checks if the instance is configured to use LocalStack by verifying the presence of the LOCALSTACK_HOSTNAME
 * environment variable.
 * @returns {boolean}
 * @constructor
 */
const InstanceIsLocalStackEnabled = () =>
  isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME);

/**
 * Returns the LocalStack endpoint URL based on the LOCALSTACK_HOSTNAME environment variable.
 * @returns {`http://${*}:4566`}
 * @constructor
 */
const InstanceLocalStackEndpoint = () => `http://${process.env.LOCALSTACK_HOSTNAME}:4566`;

/**
 * Returns the appropriate endpoints for the current instance, which can be used for making API calls or other network
 * requests.
 * @returns {*|null}
 * @constructor
 */
const InstanceEndpoints = () =>
  InstanceManager({
    imex:
      process.env?.NODE_ENV === "development"
        ? "https://localhost:3000"
        : process.env?.NODE_ENV === "test"
          ? "https://test.imex.online"
          : "https://imex.online",
    rome:
      process.env?.NODE_ENV === "development"
        ? "https://localhost:3000"
        : process.env?.NODE_ENV === "test"
          ? "https://test.romeonline.io"
          : "https://romeonline.io"
  });

module.exports = {
  InstanceManager,
  InstanceRegion,
  InstanceIsLocalStackEnabled,
  InstanceLocalStackEndpoint,
  InstanceEndpoints,
  default: InstanceManager
};
