import { FileLogger } from './file-logger.js';
import { getLogsDir } from './utils.js';
import { join } from 'path';
import { inspect } from 'util';
let isVerbose = false;
let isJsonMode = false;
let fileLogger = null;
export function setVerbose(verbose) {
    isVerbose = verbose;
    if (verbose) {
        currentLogLevel = 'debug';
    }
}
export function getVerbose() {
    return isVerbose;
}
export function setJsonMode(json) {
    isJsonMode = json;
}
export function getJsonMode() {
    return isJsonMode;
}
export async function initFileLogger(logFileName, options) {
    if (fileLogger) {
        log('warn', 'Logging file already open?');
        await fileLogger.close();
    }
    const filePath = join(getLogsDir(), logFileName);
    fileLogger = new FileLogger({
        filePath,
        maxSize: 10 * 1024 * 1024,
        maxFiles: 5,
    });
    await fileLogger.init();
    const timestamp = new Date().toISOString();
    fileLogger.write(`[${timestamp}] ========================================`);
    if (options?.version) {
        fileLogger.write(`[${timestamp}] mcpc v${options.version}`);
    }
    if (options?.command) {
        fileLogger.write(`[${timestamp}] Command: ${options.command}`);
    }
    fileLogger.write(`[${timestamp}] ========================================`);
}
export async function closeFileLogger() {
    if (fileLogger) {
        const copy = fileLogger;
        fileLogger = null;
        await copy.close();
    }
}
const LOG_LEVELS = {
    debug: 0,
    info: 1,
    warn: 2,
    error: 3,
};
let currentLogLevel = 'info';
export function setLogLevel(level) {
    currentLogLevel = level;
}
function shouldLog(level) {
    if (isJsonMode) {
        return false;
    }
    if (level === 'debug' && !isVerbose) {
        return false;
    }
    return LOG_LEVELS[level] >= LOG_LEVELS[currentLogLevel];
}
function formatMessage(level, message, forFile = false) {
    const includeTimestamp = forFile || isVerbose;
    if (includeTimestamp) {
        const timestamp = new Date().toISOString();
        return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
    }
    return message;
}
function formatExceptionChain(error, indent = '') {
    const lines = [];
    lines.push(`${indent}${error.name || 'Error'}: ${error.message}`);
    if (error.stack) {
        const stackLines = error.stack.split('\n').slice(1);
        for (const line of stackLines) {
            lines.push(`${indent}${line}`);
        }
    }
    const extraProps = Object.getOwnPropertyNames(error).filter((p) => !['name', 'message', 'stack', 'cause'].includes(p));
    if (extraProps.length > 0) {
        for (const prop of extraProps) {
            const value = error[prop];
            lines.push(`${indent}  ${prop}: ${inspect(value, { depth: 2, colors: false, compact: true })}`);
        }
    }
    if ('cause' in error && error.cause) {
        lines.push(`${indent}Cause:`);
        if (error.cause instanceof Error) {
            lines.push(formatExceptionChain(error.cause, indent + '  '));
        }
        else {
            lines.push(`${indent}  ${inspect(error.cause, { depth: 4, colors: false, compact: true })}`);
        }
    }
    return lines.join('\n');
}
function formatArg(arg) {
    if (typeof arg === 'string') {
        return arg;
    }
    if (arg instanceof Error) {
        return formatExceptionChain(arg);
    }
    if (typeof arg === 'object' && arg !== null) {
        return inspect(arg, { depth: 4, colors: false, compact: true });
    }
    return JSON.stringify(arg);
}
function writeToFile(level, message, args) {
    if (!fileLogger)
        return;
    let fullMessage = formatMessage(level, message, true);
    if (args.length > 0) {
        const argsStr = args.map(formatArg).join(' ');
        fullMessage = `${fullMessage} ${argsStr}`;
    }
    fileLogger.write(fullMessage);
}
export function debug(message, ...args) {
    if (shouldLog('debug')) {
        console.error(formatMessage('debug', message), ...args);
    }
    writeToFile('debug', message, args);
}
export function info(message, ...args) {
    if (shouldLog('info')) {
        console.error(formatMessage('info', message), ...args);
    }
    writeToFile('info', message, args);
}
export function warn(message, ...args) {
    if (shouldLog('warn')) {
        console.error(formatMessage('warn', message), ...args);
    }
    writeToFile('warn', message, args);
}
export function error(message, ...args) {
    if (shouldLog('error')) {
        console.error(formatMessage('error', message), ...args);
    }
    writeToFile('error', message, args);
}
export function log(level, message, ...args) {
    switch (level) {
        case 'debug':
            debug(message, ...args);
            break;
        case 'info':
            info(message, ...args);
            break;
        case 'warn':
            warn(message, ...args);
            break;
        case 'error':
            error(message, ...args);
            break;
    }
}
export class Logger {
    context;
    constructor(context) {
        this.context = context;
    }
    formatContext(message) {
        return this.context ? `[${this.context}] ${message}` : message;
    }
    debug(message, ...args) {
        debug(this.formatContext(message), ...args);
    }
    info(message, ...args) {
        info(this.formatContext(message), ...args);
    }
    warn(message, ...args) {
        warn(this.formatContext(message), ...args);
    }
    error(message, ...args) {
        error(this.formatContext(message), ...args);
    }
    log(level, message, ...args) {
        log(level, this.formatContext(message), ...args);
    }
}
export function createLogger(context) {
    return new Logger(context);
}
class NoOpLogger extends Logger {
    constructor() {
        super();
    }
    debug() { }
    info() { }
    warn() { }
    error() { }
    log() { }
}
export function createNoOpLogger() {
    return new NoOpLogger();
}
//# sourceMappingURL=logger.js.map