/* eslint-disable no-console */
import LoggerPort from "../../ports/LoggerPort.js";
/** Log levels in order of severity. */
export const LogLevel = Object.freeze({
    DEBUG: 0,
    INFO: 1,
    WARN: 2,
    ERROR: 3,
    SILENT: 4,
});
/** Map of level names to LogLevel values. */
const LEVEL_NAMES = Object.freeze({
    debug: LogLevel.DEBUG,
    info: LogLevel.INFO,
    warn: LogLevel.WARN,
    error: LogLevel.ERROR,
    silent: LogLevel.SILENT,
});
function resolveLevel(level) {
    if (typeof level === 'string') {
        return LEVEL_NAMES[level] ?? LogLevel.INFO;
    }
    return level;
}
function resolveOptions(options) {
    const { level = LogLevel.INFO, context = {}, timestampFn } = options ?? {};
    return {
        level: resolveLevel(level),
        context: Object.freeze({ ...context }),
        timestampFn: timestampFn ?? (() => new Date().toISOString()),
    };
}
/**
 * Console logger adapter with structured JSON output.
 *
 * Provides a production-ready implementation of LoggerPort that outputs
 * structured JSON logs to the console. Supports log level filtering,
 * timestamps, and child loggers with inherited context.
 *
 * @example
 * const logger = new ConsoleLogger({ level: LogLevel.INFO });
 * logger.info('Server started', { port: 3000 });
 * // Output: {"timestamp":"...","level":"INFO","message":"Server started","port":3000}
 */
export default class ConsoleLogger extends LoggerPort {
    _level;
    _context;
    _timestampFn;
    constructor(options) {
        super();
        const resolved = resolveOptions(options);
        this._level = resolved.level;
        this._context = resolved.context;
        this._timestampFn = resolved.timestampFn;
    }
    debug(message, context) {
        this._log({ level: LogLevel.DEBUG, levelName: 'DEBUG', message, ...(context !== undefined ? { context } : {}) });
    }
    info(message, context) {
        this._log({ level: LogLevel.INFO, levelName: 'INFO', message, ...(context !== undefined ? { context } : {}) });
    }
    warn(message, context) {
        this._log({ level: LogLevel.WARN, levelName: 'WARN', message, ...(context !== undefined ? { context } : {}) });
    }
    error(message, context) {
        this._log({ level: LogLevel.ERROR, levelName: 'ERROR', message, ...(context !== undefined ? { context } : {}) });
    }
    child(context) {
        return new ConsoleLogger({
            level: this._level,
            context: { ...this._context, ...context },
            timestampFn: this._timestampFn,
        });
    }
    _log({ level, levelName, message, context }) {
        if (level < this._level) {
            return;
        }
        const entry = {
            timestamp: this._timestampFn(),
            level: levelName,
            message,
            ...this._context,
            ...context,
        };
        const output = JSON.stringify(entry);
        switch (level) {
            case LogLevel.ERROR:
                console.error(output);
                break;
            case LogLevel.WARN:
                console.warn(output);
                break;
            default:
                console.log(output);
        }
    }
}
