/**
 * Simple levelled logger.
 *
 * Levels (lowest → highest verbosity):
 *   ERROR   – always printed, fatal/unexpected failures
 *   WARNING – recoverable issues, skipped operations
 *   INFO    – normal operational events (default)
 *   DEBUG   – verbose detail for development
 *
 * Configure via LOG_LEVEL env var or by calling logger.setLevel() at runtime.
 */

const LEVELS = { ERROR: 0, WARNING: 1, INFO: 2, DEBUG: 3 };

// Aliases so callers can use warn / error as shorthands
const ALIASES = { WARN: 'WARNING', ERROR: 'ERROR' };

const COLORS = {
  ERROR:   '\x1b[31m', // red
  WARNING: '\x1b[33m', // yellow
  INFO:    '\x1b[36m', // cyan
  DEBUG:   '\x1b[35m', // magenta
  RESET:   '\x1b[0m',
  DIM:     '\x1b[2m',
};

const isTTY = process.stdout.isTTY;

let currentLevel = parseLevel(process.env.LOG_LEVEL) ?? LEVELS.INFO;

function parseLevel(str) {
  if (!str) return null;
  const upper = str.toUpperCase();
  const resolved = ALIASES[upper] ?? upper;
  return LEVELS[resolved] ?? null;
}

function setLevel(levelName) {
  const level = parseLevel(levelName);
  if (level === null) {
    log('WARNING', 'Logger', `Unknown log level "${levelName}" – keeping current level`);
    return;
  }
  currentLevel = level;
}

function getLevel() {
  return Object.keys(LEVELS).find(k => LEVELS[k] === currentLevel);
}

function timestamp() {
  return new Date().toISOString();
}

function pad(str, len) {
  return str.padEnd(len);
}

function log(levelName, tag, ...args) {
  const upper    = (ALIASES[levelName.toUpperCase()] ?? levelName.toUpperCase());
  const levelVal = LEVELS[upper];
  if (levelVal === undefined || levelVal > currentLevel) return;

  const ts      = timestamp();
  const tagStr  = tag ? `[${tag}]` : '';
  const message = args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ');

  if (isTTY) {
    const color = COLORS[upper] ?? '';
    process.stdout.write(
      `${COLORS.DIM}${ts}${COLORS.RESET} ${color}${pad(upper, 7)}${COLORS.RESET} ${COLORS.DIM}${tagStr}${COLORS.RESET} ${message}\n`
    );
  } else {
    process.stdout.write(`${ts} ${pad(upper, 7)} ${tagStr} ${message}\n`);
  }
}

// Convenience methods – each accepts (tag, ...args) OR (...args) with no tag
const logger = {
  setLevel,
  getLevel,

  error:   (tag, ...args) => log('ERROR',   tag, ...args),
  warn:    (tag, ...args) => log('WARNING', tag, ...args),
  warning: (tag, ...args) => log('WARNING', tag, ...args),
  info:    (tag, ...args) => log('INFO',    tag, ...args),
  debug:   (tag, ...args) => log('DEBUG',   tag, ...args),

  /** Log an HTTP request (DEBUG level) */
  request: (req, res, duration) => {
    log('DEBUG', 'HTTP', `${req.method} ${req.path} → ${res.statusCode} (${duration}ms)`);
  },
};

module.exports = logger;
