import { StreamResponse } from "@lib/helpers.ts";
import { writeLogEntry } from "@lib/log/fs.ts";
import { LOG_LEVEL, Logger } from "@lib/log/types.ts";
import { logLevel } from "@lib/log/constants.ts";

let longestScope = 0;

type LoggerOptions = {
  enabled?: boolean;
};

const createLogFunction = (scope: string, level: LOG_LEVEL) => {
  return (...data: unknown[]) => {
    writeLogEntry({ level, scope, args: data, date: new Date() });
    if (level < logLevel) return;
    const logFunc = {
      [LOG_LEVEL.DEBUG]: console.debug,
      [LOG_LEVEL.INFO]: console.info,
      [LOG_LEVEL.WARN]: console.warn,
      [LOG_LEVEL.ERROR]: console.error,
    }[level];

    logFunc(`[${scope.padEnd(longestScope, " ")}]`, ...data);
  };
};

export function createLogger(scope: string, _options?: LoggerOptions): Logger {
  longestScope = Math.max(scope.length, longestScope);

  return {
    debug: createLogFunction(scope, LOG_LEVEL.DEBUG),
    info: createLogFunction(scope, LOG_LEVEL.INFO),
    error: createLogFunction(scope, LOG_LEVEL.ERROR),
    warn: createLogFunction(scope, LOG_LEVEL.WARN),
  };
}

export function loggerFromStream(stream: StreamResponse) {
  return {
    debug: (...data: unknown[]) =>
      stream.enqueue(`${data.length > 1 ? data.join(" ") : data[0]}`),
    info: (...data: unknown[]) =>
      stream.enqueue(`${data.length > 1 ? data.join(" ") : data[0]}`),
    error: (...data: unknown[]) =>
      stream.enqueue(`[ERROR]: ${data.length > 1 ? data.join(" ") : data[0]}`),
    warn: (...data: unknown[]) =>
      stream.enqueue(`[WARN]: ${data.length > 1 ? data.join(" ") : data[0]}`),
  };
}

export type { Log } from "@lib/log/types.ts";
export { getLogs } from "@lib/log/fs.ts";
