const modulename = 'Logger:Base';
import fs from 'node:fs';
import path from 'node:path';
import * as rfs from 'rotating-file-stream';
import { cloneDeep, defaultsDeep } from 'lodash-es';
import consoleFactory from '@lib/console';
import { getLogSizes, getLogDivider } from './loggerUtils';
import { getTimeFilename } from '@lib/misc';
const console = consoleFactory(modulename);


/**
 * Default class for logger instances.
 * Implements log-rotate, listLogFiles() and getLogFile()
 */
export class LoggerBase {
    lrStream: rfs.RotatingFileStream;
    lrErrors = 0;
    public activeFilePath: string;
    private lrLastError: string | undefined;
    private basePath: string;
    private logNameRegex: RegExp;

    constructor(
        basePath: string,
        logName: string,
        lrDefaultOptions: rfs.Options,
        lrProfileConfig: rfs.Options | false = false
    ) {
        //Sanity check
        if (!basePath || !logName) throw new Error('Missing constructor parameters');
        this.basePath = basePath;
        this.activeFilePath = path.join(basePath, `${logName}.log`);
        this.logNameRegex = new RegExp(`^${logName}(_\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}(_\\d+)?)?.log$`);

        //If disabled
        if (lrProfileConfig === false) {
            console.warn('persistent logging disabled for:', logName);
            this.lrStream = {
                write: () => { },
            } as any as rfs.RotatingFileStream;
            return;
        }

        //Setting log rotate up
        const lrOptions = cloneDeep(lrProfileConfig);
        if (typeof lrProfileConfig === 'object') {
            defaultsDeep(lrOptions, lrDefaultOptions);
        }

        const filenameGenerator: rfs.Generator = (time, index) => {
            return time
                ? `${logName}_${getTimeFilename(time)}_${index}.log`
                : `${logName}.log`;
        };

        this.lrStream = rfs.createStream(filenameGenerator, lrOptions);
        this.lrStream.on('rotated', (filename) => {
            this.lrStream.write(getLogDivider('Log Rotated'));
            console.verbose.log(`Rotated file ${filename}`);
        });
        this.lrStream.on('error', (error) => {
            if ((error as any).code !== 'ERR_STREAM_DESTROYED') {
                console.verbose.error(error, logName);
                this.lrErrors++;
                this.lrLastError = error.message;
            }
        });
    }

    listLogFiles() {
        return getLogSizes(this.basePath, this.logNameRegex);
    }

    getLogFile(fileName: string) {
        if (!this.logNameRegex.test(fileName)) throw new Error('fileName doesn\'t match regex');
        return fs.createReadStream(path.join(this.basePath, fileName));
    }
};
