import { EventEmitter } from 'events';
import { AsyncLocalStorage } from 'async_hooks';
import pino from 'pino';
import * as path from 'path';
import * as fs from 'fs';
import { ConfigManager } from './configManager.js';
// Configuration from environment variables
const configManager = ConfigManager.getInstance();
const LOG_PATH = process.env.LOG_PATH || path.join(configManager.getLogBaseDir(), 'app.log');
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';
const LOG_SIZE_LIMIT = process.env.LOG_SIZE_LIMIT || '10m';
const LOG_INTERVAL = process.env.LOG_INTERVAL || 'daily';
// Ensure log directory exists
const logDir = ConfigManager.getInstance().getLogBaseDir();
if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir, { recursive: true });
}
/**
 * Configure Pino with multi-destination transport:
 * 1. Console (pretty-printed for development)
 * 2. File (with rotation using pino-roll)
 */
const transport = pino.transport({
    targets: [
        {
            target: 'pino-pretty',
            level: LOG_LEVEL,
            options: {
                colorize: true,
                translateTime: 'HH:MM:ss Z',
                ignore: 'pid,hostname',
            },
        },
        {
            target: 'pino-roll',
            level: LOG_LEVEL,
            options: {
                file: LOG_PATH,
                size: LOG_SIZE_LIMIT,
                frequency: LOG_INTERVAL,
                mkdir: true,
            },
        },
    ],
});
const pinoLogger = pino(transport);
/**
 * Enterprise Logger utility with Event Streaming and Async File Rotation.
 */
export class Logger {
    static emitter = new EventEmitter();
    static storage = new AsyncLocalStorage();
    static log(message, metadata, ...args) {
        const context = this.storage.getStore();
        const eventData = {
            level: 'info',
            message,
            timestamp: new Date(),
            metadata,
            runId: context?.runId,
            batchId: context?.batchId
        };
        pinoLogger.info({ ...eventData, args }, message);
        this.emitter.emit('log', eventData);
    }
    static error(message, metadata, ...args) {
        const context = this.storage.getStore();
        pinoLogger.error({ metadata, args, runId: context?.runId }, message);
        let extendedMessage = message;
        const allData = metadata ? [metadata, ...args] : args;
        if (allData.length > 0) {
            extendedMessage += "\n" + allData.map(arg => {
                if (arg instanceof Error)
                    return arg.stack || arg.message;
                if (typeof arg === 'object') {
                    try {
                        return JSON.stringify(arg, null, 2);
                    }
                    catch (e) {
                        return String(arg);
                    }
                }
                return String(arg);
            }).join("\n");
        }
        this.emitter.emit('log', {
            level: 'error',
            message: extendedMessage,
            timestamp: new Date(),
            metadata,
            runId: context?.runId,
            batchId: context?.batchId
        });
    }
    static warn(message, metadata, ...args) {
        const context = this.storage.getStore();
        pinoLogger.warn({ metadata, args, runId: context?.runId }, message);
        let extendedMessage = message;
        const allData = metadata ? [metadata, ...args] : args;
        if (allData.length > 0) {
            extendedMessage += "\n" + allData.map(arg => {
                if (arg instanceof Error)
                    return arg.stack || arg.message;
                if (typeof arg === 'object') {
                    try {
                        return JSON.stringify(arg, null, 2);
                    }
                    catch (e) {
                        return String(arg);
                    }
                }
                return String(arg);
            }).join("\n");
        }
        this.emitter.emit('log', {
            level: 'warn',
            message: extendedMessage,
            timestamp: new Date(),
            metadata,
            runId: context?.runId,
            batchId: context?.batchId
        });
    }
    static debug(message, ...args) {
        pinoLogger.debug({ args }, message);
    }
}
