/**
 * Logging utility for Vibe Feature MCP Server
 *
 * Provides structured logging with proper MCP compliance:
 * - Uses stderr for all local logging (MCP requirement)
 * - Supports MCP log message notifications to client
 * - Provides structured logging with proper levels:
 *   - debug: Tracing and detailed execution flow
 *   - info: Success operations and important milestones
 *   - warn: Expected errors and recoverable issues
 *   - error: Caught but unexpected errors
 */
export var LogLevel;
(function (LogLevel) {
    LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
    LogLevel[LogLevel["INFO"] = 1] = "INFO";
    LogLevel[LogLevel["WARN"] = 2] = "WARN";
    LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
    LogLevel[LogLevel["SILENT"] = 4] = "SILENT";
})(LogLevel || (LogLevel = {}));
// Global MCP server reference for log notifications
let mcpServerInstance = null;
// Unified logging level - can be set by MCP client or environment
let currentLoggingLevel = null;
// Test mode detection function to check at runtime
function isTestMode() {
    // Check explicit environment variables
    if (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true') {
        return true;
    }
    // Check if running in a temporary directory (common for tests)
    const cwd = process.cwd();
    if (cwd.includes('/tmp/') || cwd.includes('temp') || cwd.includes('test-')) {
        return true;
    }
    // Check if LOG_LEVEL is explicitly set to ERROR
    if (process.env.LOG_LEVEL === 'ERROR') {
        return true;
    }
    return false;
}
/**
 * Set the MCP server instance for log notifications
 */
export function setMcpServerForLogging(server) {
    mcpServerInstance = server;
}
/**
 * Set the logging level from MCP client request
 */
export function setMcpLoggingLevel(level) {
    // Map MCP levels to our internal levels
    const levelMap = {
        debug: LogLevel.DEBUG,
        info: LogLevel.INFO,
        notice: LogLevel.INFO,
        warning: LogLevel.WARN,
        error: LogLevel.ERROR,
        critical: LogLevel.ERROR,
        alert: LogLevel.ERROR,
        emergency: LogLevel.ERROR,
    };
    currentLoggingLevel = levelMap[level] ?? LogLevel.INFO;
}
class Logger {
    component;
    explicitLogLevel;
    constructor(component, logLevel) {
        this.component = component;
        this.explicitLogLevel = logLevel;
    }
    getCurrentLogLevel() {
        // Check environment variable first (allows SILENT to override test mode)
        const envLevel = this.getLogLevelFromEnv();
        if (envLevel === LogLevel.SILENT) {
            return LogLevel.SILENT;
        }
        // Force ERROR level in test environments (unless SILENT)
        if (isTestMode()) {
            return LogLevel.ERROR;
        }
        // Use MCP-set level if available (takes precedence)
        if (currentLoggingLevel !== null) {
            return currentLoggingLevel;
        }
        // Use environment variable level
        if (envLevel !== null) {
            return envLevel;
        }
        // If explicit log level was provided, use it
        if (this.explicitLogLevel !== undefined) {
            return this.explicitLogLevel;
        }
        // Default to INFO
        return LogLevel.INFO;
    }
    getLogLevelFromEnv() {
        const envLevel = process.env.LOG_LEVEL?.toUpperCase();
        switch (envLevel) {
            case 'DEBUG':
                return LogLevel.DEBUG;
            case 'INFO':
                return LogLevel.INFO;
            case 'WARN':
                return LogLevel.WARN;
            case 'ERROR':
                return LogLevel.ERROR;
            case 'SILENT':
                return LogLevel.SILENT;
            default:
                return null;
        }
    }
    shouldLog(level) {
        return level >= this.getCurrentLogLevel();
    }
    formatMessage(level, message, context) {
        const timestamp = new Date().toISOString();
        const contextStr = context ? ` ${JSON.stringify(context)}` : '';
        return `[${timestamp}] ${level.toUpperCase()} [${this.component}] ${message}${contextStr}`;
    }
    /**
     * Send log message to MCP client if server is available and level is appropriate
     */
    async sendMcpLogMessage(level, message, context) {
        if (mcpServerInstance) {
            try {
                // Safely serialize context to avoid JSON issues
                let logData = message;
                if (context) {
                    try {
                        const contextStr = JSON.stringify(context, null, 0);
                        logData = `${message} ${contextStr}`;
                    }
                    catch (_error) {
                        // If JSON serialization fails, just use the message
                        logData = `${message} [context serialization failed]`;
                    }
                }
                await mcpServerInstance.server.notification({
                    method: 'notifications/message',
                    params: {
                        level,
                        logger: this.component,
                        data: logData,
                    },
                });
            }
            catch (error) {
                // Fallback to stderr if MCP notification fails
                // Don't use this.error to avoid infinite recursion
                if (!isTestMode()) {
                    process.stderr.write(`[MCP-LOG-ERROR] Failed to send log notification: ${error}\n`);
                }
            }
        }
    }
    debug(message, context) {
        if (this.shouldLog(LogLevel.DEBUG)) {
            const formattedMessage = this.formatMessage('debug', message, context);
            // Always log to stderr for MCP compliance
            process.stderr.write(formattedMessage + '\n');
            // Also send to MCP client if available (only for debug level)
            this.sendMcpLogMessage('debug', message, context).catch(() => {
                // Ignore MCP notification errors for debug messages
            });
        }
    }
    info(message, context) {
        if (this.shouldLog(LogLevel.INFO)) {
            const formattedMessage = this.formatMessage('info', message, context);
            // Always log to stderr for MCP compliance
            process.stderr.write(formattedMessage + '\n');
            // Send enhanced notifications for important events
            this.sendEnhancedMcpNotification('info', message, context).catch(() => {
                // Ignore MCP notification errors for info messages
            });
        }
    }
    /**
     * Send enhanced MCP notifications with better formatting for important events
     */
    async sendEnhancedMcpNotification(level, message, context) {
        if (mcpServerInstance) {
            try {
                let enhancedMessage = message;
                let notificationLevel = level;
                // Enhance phase transition messages
                if (context &&
                    (context.from || context.to) &&
                    message.includes('transition')) {
                    const from = context.from
                        ? this.capitalizePhase(context.from)
                        : '';
                    const to = context.to
                        ? this.capitalizePhase(context.to)
                        : '';
                    if (from && to) {
                        enhancedMessage = `Phase Transition: ${from} → ${to}`;
                        notificationLevel = 'info';
                    }
                }
                // Enhance initialization messages
                if (message.includes('initialized successfully')) {
                    enhancedMessage = '🚀 Vibe Feature MCP Server Ready';
                    notificationLevel = 'info';
                }
                // Safely serialize context to avoid JSON issues
                let logData = enhancedMessage;
                if (context) {
                    try {
                        const contextStr = JSON.stringify(context, null, 0);
                        logData = `${enhancedMessage} ${contextStr}`;
                    }
                    catch (_error) {
                        // If JSON serialization fails, just use the message
                        logData = `${enhancedMessage} [context serialization failed]`;
                    }
                }
                // Use the underlying server's notification method
                await mcpServerInstance.server.notification({
                    method: 'notifications/message',
                    params: {
                        level: notificationLevel,
                        logger: this.component,
                        data: logData,
                    },
                });
            }
            catch (error) {
                // Fallback to stderr if MCP notification fails
                // Don't use this.error to avoid infinite recursion
                if (!isTestMode()) {
                    process.stderr.write(`[MCP-LOG-ERROR] Failed to send log notification: ${error}\n`);
                }
            }
        }
    }
    /**
     * Capitalize phase name for display
     */
    capitalizePhase(phase) {
        return phase
            .split('_')
            .map(word => word.charAt(0).toUpperCase() + word.slice(1))
            .join(' ');
    }
    warn(message, context) {
        if (this.shouldLog(LogLevel.WARN)) {
            const formattedMessage = this.formatMessage('warn', message, context);
            // Always log to stderr for MCP compliance
            process.stderr.write(formattedMessage + '\n');
            // Also send to MCP client if available
            this.sendEnhancedMcpNotification('warning', message, context).catch(() => {
                // Ignore MCP notification errors for warn messages
            });
        }
    }
    error(message, error, context) {
        if (this.shouldLog(LogLevel.ERROR)) {
            const errorContext = error
                ? { ...context, error: error.message, stack: error.stack }
                : context;
            const formattedMessage = this.formatMessage('error', message, errorContext);
            // Always log to stderr for MCP compliance
            process.stderr.write(formattedMessage + '\n');
            // Also send to MCP client if available
            this.sendEnhancedMcpNotification('error', message, errorContext).catch(() => {
                // Ignore MCP notification errors for error messages
            });
        }
    }
    child(childComponent) {
        return new Logger(`${this.component}:${childComponent}`, this.explicitLogLevel);
    }
}
// Factory function to create loggers
export function createLogger(component, logLevel) {
    return new Logger(component, logLevel);
}
// Default logger for the main application
export const logger = createLogger('VibeFeatureMCP');
//# sourceMappingURL=logger.js.map