import winston from 'winston';
import path from 'path';
import fs from 'fs';
import { EventEmitter } from 'events';
const logDir = path.resolve(process.cwd(), 'logs');
if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir, { recursive: true });
}
class ConsoleLogBuffer extends EventEmitter {
    constructor() {
        super(...arguments);
        this.buffer = [];
        this.maxBufferSize = 500;
        this.io = null;
        this.originalStdoutWrite = null;
        this.originalStderrWrite = null;
        this.isCapturing = false;
    }
    setSocketIO(io) {
        this.io = io;
    }
    startCapturing() {
        if (this.isCapturing)
            return;
        this.isCapturing = true;
        this.originalStdoutWrite = process.stdout.write.bind(process.stdout);
        this.originalStderrWrite = process.stderr.write.bind(process.stderr);
        process.stdout.write = ((chunk, encoding, callback) => {
            const text = typeof chunk === 'string' ? chunk : chunk.toString();
            const lines = text.split('\n').filter((line) => line.trim());
            lines.forEach((line) => this.addLog(line));
            return this.originalStdoutWrite(chunk, encoding, callback);
        });
        process.stderr.write = ((chunk, encoding, callback) => {
            const text = typeof chunk === 'string' ? chunk : chunk.toString();
            const lines = text.split('\n').filter((line) => line.trim());
            lines.forEach((line) => this.addLog(`[ERROR] ${line}`));
            return this.originalStderrWrite(chunk, encoding, callback);
        });
    }
    stopCapturing() {
        if (!this.isCapturing)
            return;
        this.isCapturing = false;
        if (this.originalStdoutWrite) {
            process.stdout.write = this.originalStdoutWrite;
        }
        if (this.originalStderrWrite) {
            process.stderr.write = this.originalStderrWrite;
        }
    }
    addLog(log) {
        const cleanLog = log.replace(/\x1B\[[0-9;]*[mGKH]/g, '');
        this.buffer.push(cleanLog);
        if (this.buffer.length > this.maxBufferSize) {
            this.buffer.shift();
        }
        this.emit('log', cleanLog);
        if (this.io) {
            this.io.to('console-logs').emit('console-log', { line: cleanLog });
        }
    }
    getRecentLogs(count = 100) {
        return this.buffer.slice(-count);
    }
    clear() {
        this.buffer = [];
    }
}
export const consoleLogBuffer = new ConsoleLogBuffer();
consoleLogBuffer.startCapturing();
const logFormat = winston.format.combine(winston.format.timestamp({
    format: 'YYYY-MM-DD HH:mm:ss'
}), winston.format.errors({ stack: true }), winston.format.printf(({ timestamp, level, message, stack }) => {
    return `${timestamp} [${level.toUpperCase()}]: ${stack || message}`;
}));
const logger = winston.createLogger({
    level: process.env.LOG_LEVEL || 'info',
    format: logFormat,
    transports: [
        new winston.transports.Console({
            format: winston.format.combine(winston.format.colorize(), logFormat)
        }),
        new winston.transports.File({
            filename: path.join(logDir, 'app.log'),
            maxsize: 10 * 1024 * 1024,
            maxFiles: 5,
            tailable: true
        }),
        new winston.transports.File({
            filename: path.join(logDir, 'error.log'),
            level: 'error',
            maxsize: 10 * 1024 * 1024,
            maxFiles: 5,
            tailable: true
        }),
        new winston.transports.File({
            filename: path.join(logDir, 'terminal.log'),
            level: 'info',
            maxsize: 50 * 1024 * 1024,
            maxFiles: 3,
            tailable: true,
            format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, level, message }) => {
                return `${timestamp} [TERMINAL]: ${message}`;
            }))
        }),
        new winston.transports.File({
            filename: path.join(logDir, 'games.log'),
            level: 'info',
            maxsize: 50 * 1024 * 1024,
            maxFiles: 3,
            tailable: true,
            format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, level, message }) => {
                return `${timestamp} [GAMES]: ${message}`;
            }))
        }),
        new winston.transports.File({
            filename: path.join(logDir, 'system.log'),
            level: 'info',
            maxsize: 20 * 1024 * 1024,
            maxFiles: 3,
            tailable: true,
            format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, level, message }) => {
                return `${timestamp} [SYSTEM]: ${message}`;
            }))
        })
    ],
    exceptionHandlers: [
        new winston.transports.File({
            filename: path.join(logDir, 'exceptions.log'),
            maxsize: 10 * 1024 * 1024,
            maxFiles: 3
        })
    ],
    rejectionHandlers: [
        new winston.transports.File({
            filename: path.join(logDir, 'rejections.log'),
            maxsize: 10 * 1024 * 1024,
            maxFiles: 3
        })
    ]
});
export const terminalLogger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, message }) => {
        return `${timestamp} ${message}`;
    })),
    transports: [
        new winston.transports.File({
            filename: path.join(logDir, 'terminal.log'),
            maxsize: 50 * 1024 * 1024,
            maxFiles: 3,
            tailable: true
        })
    ]
});
export const gameLogger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, message }) => {
        return `${timestamp} ${message}`;
    })),
    transports: [
        new winston.transports.File({
            filename: path.join(logDir, 'games.log'),
            maxsize: 50 * 1024 * 1024,
            maxFiles: 3,
            tailable: true
        })
    ]
});
export const systemLogger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, message }) => {
        return `${timestamp} ${message}`;
    })),
    transports: [
        new winston.transports.File({
            filename: path.join(logDir, 'system.log'),
            maxsize: 20 * 1024 * 1024,
            maxFiles: 3,
            tailable: true
        })
    ]
});
if (process.env.NODE_ENV === 'production') {
    logger.remove(logger.transports[0]);
}
export default logger;
