import * as winston from 'winston';


export class Logger {
    #consoleTransport;
    #fileTransport;
    #logger;

    constructor() {
        const consoleFormat = winston.format.combine(
            winston.format.colorize(),
            winston.format.timestamp({ format: 'HH:mm:ss'}),
            winston.format.printf(({ level, message, timestamp, ...meta }) => {
                const reqId = meta.requestId ? ` [reqId:${meta.requestId}]` : '';
                return `[${timestamp}] ${level}:${reqId} ${message}`;
            })
        );

        this.#consoleTransport = new winston.transports.Console({
            level: 'error',
            format: consoleFormat
        });

        this.#logger = winston.createLogger({
            transports: [ this.#consoleTransport ]
        });
    }

    enableFileLogging(filePath) {
        if (this.#fileTransport) return; // already enabled
        
        this.#fileTransport = new winston.transports.File({
            filename: filePath,
            level: 'debug',
            format: winston.format.combine(
                winston.format.timestamp(),
                winston.format.json()
            )
        });
        this.#logger.add(this.#fileTransport);
    }

    get level() {
        return this.#consoleTransport.level;
    }

    set level(level) {
        this.#consoleTransport.level = level;
        if (this.#fileTransport) {
            this.#fileTransport.level = level;
        }
    }

    muteConsole()   { this.#consoleTransport.silent = true; }
    unmuteConsole() { this.#consoleTransport.silent = false; }

    info(msg, meta = {}) { this.#logger.info(msg, meta); }
    error(msg, meta = {}) { this.#logger.error(msg, meta); }
    debug(msg, meta = {}) { this.#logger.debug(msg, meta); }
    warn(msg, meta = {}) { this.#logger.warn(msg, meta); }
    verbose(msg, meta = {}) { this.#logger.verbose(msg, meta); }
    silly(msg, meta = {}) { this.#logger.silly(msg, meta); }
}

export const logger = new Logger();
