const LEVEL_WEIGHTS = {
  error: 0,
  warn: 1,
  info: 2,
  debug: 3,
};

const DEFAULT_LOG_LEVEL = "info";

function normalizeLogLevel(value = process.env.LOG_LEVEL) {
  const normalized = String(value ?? "").trim().toLowerCase();
  return Object.prototype.hasOwnProperty.call(LEVEL_WEIGHTS, normalized)
    ? normalized
    : DEFAULT_LOG_LEVEL;
}

function isLevelEnabled(level, configuredLevel = process.env.LOG_LEVEL) {
  const normalizedLevel = normalizeLogLevel(level);
  const normalizedConfiguredLevel = normalizeLogLevel(configuredLevel);
  return LEVEL_WEIGHTS[normalizedLevel] <= LEVEL_WEIGHTS[normalizedConfiguredLevel];
}

function writeLog(level, ...args) {
  if (!isLevelEnabled(level)) {
    return;
  }

  const normalizedLevel = normalizeLogLevel(level);
  const writer = normalizedLevel === "debug"
    ? console.debug
    : normalizedLevel === "info"
      ? console.log
      : normalizedLevel === "warn"
        ? console.warn
        : console.error;
  writer(...args);
}

function createLogger(scope) {
  const prefix = scope ? `[${scope}]` : "";
  const withPrefix = (args) => (prefix ? [prefix, ...args] : args);

  return {
    error: (...args) => writeLog("error", ...withPrefix(args)),
    warn: (...args) => writeLog("warn", ...withPrefix(args)),
    info: (...args) => writeLog("info", ...withPrefix(args)),
    debug: (...args) => writeLog("debug", ...withPrefix(args)),
    isDebugEnabled: () => isLevelEnabled("debug"),
  };
}

const rootLogger = createLogger("");

export {
  DEFAULT_LOG_LEVEL,
  LEVEL_WEIGHTS,
  createLogger,
  isLevelEnabled,
  normalizeLogLevel,
  rootLogger as logger,
  writeLog,
};
