import { Logger, LogLevel } from '@common/Logger';

describe('Logger — leveled logging', () => {
    let logger: Logger;
    let sink: jest.Mock;

    beforeEach(() => {
        logger = new Logger();
        sink = jest.fn();
        logger.setSink(sink);
    });

    it('suppresses messages below the threshold', () => {
        logger.setLevel(LogLevel.Warn);
        logger.debug('mod', 'hidden');
        logger.info('mod', 'hidden');
        logger.warn('mod', 'shown');
        logger.error('mod', 'shown');
        expect(sink).toHaveBeenCalledTimes(2);
    });

    it('forwards module + message + rest args to the sink', () => {
        logger.setLevel(LogLevel.Debug);
        logger.info('Pool', 'size', 5);
        expect(sink).toHaveBeenCalledWith(LogLevel.Info, 'Pool', 'size', 5);
    });

    it('Silent level disables all output', () => {
        logger.setLevel(LogLevel.Silent);
        logger.error('mod', 'ignored');
        expect(sink).not.toHaveBeenCalled();
    });
});

describe('Logger — performance metrics', () => {
    let logger: Logger;

    beforeEach(() => {
        logger = new Logger();
    });

    it('records samples under a metric name', () => {
        for (const v of [10, 20, 30, 40, 50]) {
            logger.metric({ name: 'touch_ms', value: v });
        }
        const agg = logger.aggregate('touch_ms');
        expect(agg).toBeDefined();
        expect(agg!.count).toBe(5);
        expect(agg!.min).toBe(10);
        expect(agg!.max).toBe(50);
        expect(agg!.avg).toBeCloseTo(30);
        expect(agg!.p50).toBe(30);
        expect(agg!.p95).toBe(50);
    });

    it('returns undefined aggregate for unknown metric', () => {
        expect(logger.aggregate('ghost')).toBeUndefined();
    });

    it('timerStart/timerEnd records elapsed time', () => {
        logger.timerStart('frame', 1000);
        const elapsed = logger.timerEnd('frame', 1016);
        expect(elapsed).toBe(16);
        expect(logger.aggregate('frame')!.avg).toBe(16);
    });

    it('timerEnd without start returns undefined', () => {
        expect(logger.timerEnd('never', 100)).toBeUndefined();
    });

    it('resetMetrics clears all samples and running timers', () => {
        logger.metric({ name: 'a', value: 1 });
        logger.timerStart('b', 0);
        logger.resetMetrics();
        expect(logger.aggregate('a')).toBeUndefined();
        expect(logger.timerEnd('b', 10)).toBeUndefined();
    });
});
