/**
 * logger.ts — Sistema de logging para debug en producción (cPanel/CloudLinux)
 *
 * - Escribe en consola (capturado por cPanel Node.js App logs)
 * - Mantiene un ring-buffer en memoria de los últimos 200 eventos
 * - Accesible vía /api/debug?token=DEBUG_TOKEN
 */

export type LogLevel = "INFO" | "WARN" | "ERROR" | "DEBUG";

export interface LogEntry {
  id: number;
  ts: string;           // ISO timestamp
  level: LogLevel;
  ctx: string;          // contexto: "prisma", "auth", "api", "action", etc.
  msg: string;
  data?: unknown;       // payload adicional (error, query, etc.)
}

// ─── Ring buffer en memoria ────────────────────────────────────────────────
const MAX_LOGS = 200;
let logId = 0;
const logBuffer: LogEntry[] = [];

function push(entry: LogEntry) {
  if (logBuffer.length >= MAX_LOGS) logBuffer.shift();
  logBuffer.push(entry);
}

// ─── Formateador de consola ────────────────────────────────────────────────
function fmt(entry: LogEntry): string {
  const data = entry.data !== undefined
    ? "\n  " + JSON.stringify(entry.data, null, 2).replace(/\n/g, "\n  ")
    : "";
  return `[${entry.ts}] [${entry.level}] [${entry.ctx}] ${entry.msg}${data}`;
}

// ─── Función base ──────────────────────────────────────────────────────────
function log(level: LogLevel, ctx: string, msg: string, data?: unknown) {
  const entry: LogEntry = {
    id: ++logId,
    ts: new Date().toISOString(),
    level,
    ctx,
    msg,
    data: data instanceof Error
      ? { name: data.name, message: data.message, stack: data.stack }
      : data,
  };

  push(entry);

  const formatted = fmt(entry);
  switch (level) {
    case "ERROR": console.error(formatted); break;
    case "WARN":  console.warn(formatted);  break;
    case "DEBUG": console.debug(formatted); break;
    default:      console.log(formatted);   break;
  }
}

// ─── API pública ───────────────────────────────────────────────────────────
export const logger = {
  info:  (ctx: string, msg: string, data?: unknown) => log("INFO",  ctx, msg, data),
  warn:  (ctx: string, msg: string, data?: unknown) => log("WARN",  ctx, msg, data),
  error: (ctx: string, msg: string, data?: unknown) => log("ERROR", ctx, msg, data),
  debug: (ctx: string, msg: string, data?: unknown) => log("DEBUG", ctx, msg, data),

  /** Retorna todos los logs en memoria (para el endpoint /api/debug) */
  getLogs: (): LogEntry[] => [...logBuffer].reverse(),

  /** Limpia el buffer */
  clear: () => { logBuffer.length = 0; logId = 0; },
};

// ─── Intercepta errores no capturados del proceso Node.js ─────────────────
if (typeof process !== "undefined") {
  process.on("uncaughtException", (err) => {
    logger.error("process", "uncaughtException", err);
  });
  process.on("unhandledRejection", (reason) => {
    logger.error("process", "unhandledRejection", reason);
  });
}

export default logger;
