"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogPurgeService = void 0;
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const logger_1 = require("../logger");
class LogPurgeService {
    constructor(options) {
        this.options = options;
    }
    /**
     * Purges logs older than the specified retention period
     */
    async purgeOldLogs() {
        const result = {
            filesPurged: 0,
            spaceFreed: 0,
            errors: [],
            purgedFiles: []
        };
        try {
            const cutoffDate = new Date();
            cutoffDate.setDate(cutoffDate.getDate() - this.options.retentionDays);
            logger_1.logger.info(`Starting log purge - removing files older than ${cutoffDate.toISOString()}`);
            const files = await this.getAllLogFiles();
            for (const filePath of files) {
                try {
                    const stats = await fs_1.promises.stat(filePath);
                    if (stats.mtime < cutoffDate) {
                        const fileSize = stats.size;
                        if (!this.options.dryRun) {
                            await fs_1.promises.unlink(filePath);
                            result.purgedFiles.push(filePath);
                        }
                        result.filesPurged++;
                        result.spaceFreed += fileSize;
                        const action = this.options.dryRun ? 'Would purge' : 'Purged';
                        logger_1.logger.info(`${action} old log file: ${path_1.default.basename(filePath)} (${this.formatBytes(fileSize)})`);
                    }
                }
                catch (error) {
                    const errorMsg = `Failed to process file ${filePath}: ${error}`;
                    result.errors.push(errorMsg);
                    logger_1.logger.error(errorMsg);
                }
            }
            logger_1.logger.info(`Log purge completed - ${result.filesPurged} files ${this.options.dryRun ? 'would be' : ''} purged, ${this.formatBytes(result.spaceFreed)} ${this.options.dryRun ? 'would be' : ''} freed`);
            return result;
        }
        catch (error) {
            const errorMsg = `Failed to purge logs: ${error}`;
            result.errors.push(errorMsg);
            logger_1.logger.error(errorMsg);
            return result;
        }
    }
    /**
     * Gets all log files in the logs directory and subdirectories
     */
    async getAllLogFiles() {
        const logFiles = [];
        try {
            await this.scanDirectory(this.options.logsDirectory, logFiles);
            return logFiles;
        }
        catch (error) {
            logger_1.logger.error(`Failed to scan logs directory: ${error}`);
            return [];
        }
    }
    /**
     * Recursively scans directory for log files
     */
    async scanDirectory(dirPath, logFiles) {
        try {
            const entries = await fs_1.promises.readdir(dirPath, { withFileTypes: true });
            for (const entry of entries) {
                const fullPath = path_1.default.join(dirPath, entry.name);
                if (entry.isDirectory()) {
                    // Recursively scan subdirectories
                    await this.scanDirectory(fullPath, logFiles);
                }
                else if (entry.isFile() && this.isLogFile(entry.name)) {
                    logFiles.push(fullPath);
                }
            }
        }
        catch (error) {
            logger_1.logger.warn(`Failed to scan directory ${dirPath}: ${error}`);
        }
    }
    /**
     * Determines if a file is a log file based on its extension and name
     */
    isLogFile(filename) {
        const logExtensions = ['.log', '.json'];
        const logPatterns = ['error', 'access', 'debug', 'info', 'warn', 'trace'];
        const ext = path_1.default.extname(filename).toLowerCase();
        const name = filename.toLowerCase();
        // Check for log extensions
        if (logExtensions.includes(ext)) {
            return true;
        }
        // Check for log patterns in filename
        return logPatterns.some(pattern => name.includes(pattern));
    }
    /**
     * Gets statistics about the logs directory
     */
    async getLogsDirectoryStats() {
        const stats = {
            totalFiles: 0,
            totalSize: 0,
            oldestFile: null,
            newestFile: null,
            filesByAge: {}
        };
        try {
            const files = await this.getAllLogFiles();
            for (const filePath of files) {
                try {
                    const fileStats = await fs_1.promises.stat(filePath);
                    stats.totalFiles++;
                    stats.totalSize += fileStats.size;
                    // Update oldest/newest file dates
                    if (!stats.oldestFile || fileStats.mtime < stats.oldestFile) {
                        stats.oldestFile = fileStats.mtime;
                    }
                    if (!stats.newestFile || fileStats.mtime > stats.newestFile) {
                        stats.newestFile = fileStats.mtime;
                    }
                    // Categorize files by age
                    const ageInDays = Math.floor((Date.now() - fileStats.mtime.getTime()) / (1000 * 60 * 60 * 24));
                    const ageCategory = this.getAgeCategory(ageInDays);
                    stats.filesByAge[ageCategory] = (stats.filesByAge[ageCategory] || 0) + 1;
                }
                catch (error) {
                    logger_1.logger.warn(`Failed to get stats for file ${filePath}: ${error}`);
                }
            }
            return stats;
        }
        catch (error) {
            logger_1.logger.error(`Failed to get logs directory stats: ${error}`);
            return stats;
        }
    }
    /**
     * Categorizes file age into human-readable categories
     */
    getAgeCategory(ageInDays) {
        if (ageInDays < 1)
            return 'Today';
        if (ageInDays < 7)
            return 'This Week';
        if (ageInDays < 30)
            return 'This Month';
        if (ageInDays < 90)
            return 'This Quarter';
        return 'Older';
    }
    /**
     * Formats bytes into human-readable format
     */
    formatBytes(bytes) {
        if (bytes === 0)
            return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
    /**
     * Schedules automatic log purging
     */
    schedulePurge(intervalHours = 24) {
        const intervalMs = intervalHours * 60 * 60 * 1000;
        logger_1.logger.info(`Scheduling log purge every ${intervalHours} hours`);
        return setInterval(async () => {
            try {
                logger_1.logger.info('Starting scheduled log purge');
                const result = await this.purgeOldLogs();
                logger_1.logger.info(`Scheduled purge completed: ${result.filesPurged} files purged, ${this.formatBytes(result.spaceFreed)} freed`);
            }
            catch (error) {
                logger_1.logger.error(`Scheduled log purge failed: ${error}`);
            }
        }, intervalMs);
    }
}
exports.LogPurgeService = LogPurgeService;
//# sourceMappingURL=logPurgeService.js.map