import rTracer from "cls-rtracer";
import { createLogger, format, transports } from "winston";
import { ILogger } from "../types";

const winston = createLogger({
  level: "info",
  format: format.combine(
    format.colorize(),
    format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
    format.errors({ stack: true }),
    format.align(),
    format.splat(),
    format.json(),
    format.printf((info) => {
      const { level, timestamp, stack, label, meta, error } = info;
      const rid = rTracer.id();
      let message = info.message;

      if (typeof message === "object") {
        message = JSON.stringify(message);
      }

      let out = `${timestamp}`;

      if (rid) {
        out = `${out} [request-id:${rid}]`;
      }

      out = `${out} - ${level}: [${label}]: ${message}`;
      if (stack) {
        out = `${out} - ${stack}`;
      }

      if (meta) {
        out = `${out} - ${JSON.stringify(meta, null, 3)}`;
      }

      if (error) {
        out = `${out} - ${JSON.stringify(error, null, 3)}`;
      }

      return out;
    })
  ),
  transports: [new transports.Console()],
});

export class WinstonLogger implements ILogger {
  debug(message: string, meta?: any): void {
    winston.debug(message, meta ?? {});
  }
  info(message: string, meta?: any) {
    winston.info(message, meta ?? {});
  }

  warn(message: string, meta?: any) {
    winston.warn(message, meta ?? {});
  }

  error(message: string, error?: any) {
    winston.error(message, { error: error?.stack || error });
  }
}

export const createWinstonLogger = (): ILogger => new WinstonLogger();
