"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = exports.Logger = exports.LogLevel = void 0;
exports.createDefaultLogger = createDefaultLogger;
exports.createWinstonLogger = createWinstonLogger;
const winston_1 = __importDefault(require("winston"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const projectrootpath_1 = require("../projectrootpath");
/**
 * Log levels for different types of messages
 */
var LogLevel;
(function (LogLevel) {
    LogLevel["INFO"] = "INFO";
    LogLevel["WARN"] = "WARN";
    LogLevel["ERROR"] = "ERROR";
    LogLevel["DEBUG"] = "DEBUG";
})(LogLevel || (exports.LogLevel = LogLevel = {}));
/**
 * Logger class for writing logs to a file
 */
class Logger {
    /**
     * Creates a new Logger instance
     * @param config Logger configuration
     */
    constructor(config) {
        var _a, _b;
        this.filePath = config.filePath;
        this.logToConsole = (_a = config.logToConsole) !== null && _a !== void 0 ? _a : true;
        this.minLevel = (_b = config.minLevel) !== null && _b !== void 0 ? _b : LogLevel.INFO;
        // Ensure the directory exists
        const dir = path_1.default.dirname(this.filePath);
        if (!fs_1.default.existsSync(dir)) {
            fs_1.default.mkdirSync(dir, { recursive: true });
        }
    }
    /**
     * Writes a log entry to the file
     * @param level Log level
     * @param message Log message
     * @param data Additional data to log (optional)
     */
    log(level, message, data) {
        // Skip if below minimum log level
        if (this.shouldSkip(level)) {
            return;
        }
        const timestamp = new Date().toISOString();
        let logEntry = `[${timestamp}] [${level}] ${message}`;
        if (data) {
            if (typeof data === 'object') {
                try {
                    logEntry += `\n${JSON.stringify(data, null, 2)}`;
                }
                catch (err) {
                    logEntry += `\n[Object serialization failed]`;
                }
            }
            else {
                logEntry += `\n${data}`;
            }
        }
        logEntry += '\n';
        // Append to file
        fs_1.default.appendFileSync(this.filePath, logEntry);
        // Log to console if enabled
        if (this.logToConsole) {
            const consoleMethod = this.getConsoleMethod(level);
            consoleMethod(logEntry);
        }
    }
    /**
     * Determines if a log entry should be skipped based on minimum log level
     */
    shouldSkip(level) {
        const levels = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR];
        const minLevelIndex = levels.indexOf(this.minLevel);
        const currentLevelIndex = levels.indexOf(level);
        return currentLevelIndex < minLevelIndex;
    }
    /**
     * Gets the appropriate console method for the log level
     */
    getConsoleMethod(level) {
        switch (level) {
            case LogLevel.ERROR:
                return console.error;
            case LogLevel.WARN:
                return console.warn;
            case LogLevel.DEBUG:
                return console.debug;
            case LogLevel.INFO:
            default:
                return console.log;
        }
    }
    /**
     * Logs an info message
     * @param message Log message
     * @param data Additional data (optional)
     */
    info(message, data) {
        this.log(LogLevel.INFO, message, data);
    }
    /**
     * Logs a warning message
     * @param message Log message
     * @param data Additional data (optional)
     */
    warn(message, data) {
        this.log(LogLevel.WARN, message, data);
    }
    /**
     * Logs an error message
     * @param message Log message
     * @param error Error object or additional data (optional)
     */
    error(message, error) {
        this.log(LogLevel.ERROR, message, error);
    }
    /**
     * Logs a debug message
     * @param message Log message
     * @param data Additional data (optional)
     */
    debug(message, data) {
        this.log(LogLevel.DEBUG, message, data);
    }
    /**
     * Creates a new logger instance with a default configuration
     * @param filePath Path to the log file
     * @returns Logger instance
     */
    static createLogger(filePath) {
        return new Logger({ filePath });
    }
}
exports.Logger = Logger;
/**
 * Creates a default logger that writes to a file in the same directory
 * @param filename Name of the log file
 * @returns Logger instance
 */
function createDefaultLogger(filename) {
    const filePath = path_1.default.join(__dirname, filename);
    return Logger.createLogger(filePath);
}
function createWinstonLogger(toConsole = true, rootName = ".") {
    const combinedLogsFile = path_1.default.resolve(projectrootpath_1.nodejsRoot, "logs", rootName, "combined.log");
    const errorLogsFile = path_1.default.resolve(projectrootpath_1.nodejsRoot, "logs", rootName, "error.log");
    console.log("Logs will be written to: ", combinedLogsFile, errorLogsFile);
    const transports = [
        new winston_1.default.transports.Console(),
        new winston_1.default.transports.File({ filename: errorLogsFile, level: "error" }),
        new winston_1.default.transports.File({ filename: combinedLogsFile }),
    ];
    if (!toConsole) {
        transports.shift();
    }
    const logger = winston_1.default.createLogger({
        // level: "info",
        format: winston_1.default.format.combine(
        // winston.format.timestamp(),
        winston_1.default.format.printf((info) => {
            return `${info.level}: ${info.message}`;
        })),
        transports
    });
    return logger;
}
exports.logger = createWinstonLogger(true);
