<?php

declare(strict_types=1);

use App\Framework\Console\ConsoleColor;
use App\Framework\Logging\LogLevel;

describe('LogLevel', function () {
    describe('getName()', function () {
        it('returns correct name for DEBUG', function () {
            expect(LogLevel::DEBUG->getName())->toBe('DEBUG');
        });

        it('returns correct name for INFO', function () {
            expect(LogLevel::INFO->getName())->toBe('INFO');
        });

        it('returns correct name for NOTICE', function () {
            expect(LogLevel::NOTICE->getName())->toBe('NOTICE');
        });

        it('returns correct name for WARNING', function () {
            expect(LogLevel::WARNING->getName())->toBe('WARNING');
        });

        it('returns correct name for ERROR', function () {
            expect(LogLevel::ERROR->getName())->toBe('ERROR');
        });

        it('returns correct name for CRITICAL', function () {
            expect(LogLevel::CRITICAL->getName())->toBe('CRITICAL');
        });

        it('returns correct name for ALERT', function () {
            expect(LogLevel::ALERT->getName())->toBe('ALERT');
        });

        it('returns correct name for EMERGENCY', function () {
            expect(LogLevel::EMERGENCY->getName())->toBe('EMERGENCY');
        });
    });

    describe('getConsoleColor()', function () {
        it('returns GRAY for DEBUG', function () {
            expect(LogLevel::DEBUG->getConsoleColor())->toBe(ConsoleColor::GRAY);
        });

        it('returns GREEN for INFO', function () {
            expect(LogLevel::INFO->getConsoleColor())->toBe(ConsoleColor::GREEN);
        });

        it('returns CYAN for NOTICE', function () {
            expect(LogLevel::NOTICE->getConsoleColor())->toBe(ConsoleColor::CYAN);
        });

        it('returns YELLOW for WARNING', function () {
            expect(LogLevel::WARNING->getConsoleColor())->toBe(ConsoleColor::YELLOW);
        });

        it('returns RED for ERROR', function () {
            expect(LogLevel::ERROR->getConsoleColor())->toBe(ConsoleColor::RED);
        });

        it('returns MAGENTA for CRITICAL', function () {
            expect(LogLevel::CRITICAL->getConsoleColor())->toBe(ConsoleColor::MAGENTA);
        });

        it('returns WHITE_ON_RED for ALERT', function () {
            expect(LogLevel::ALERT->getConsoleColor())->toBe(ConsoleColor::WHITE_ON_RED);
        });

        it('returns BLACK_ON_YELLOW for EMERGENCY', function () {
            expect(LogLevel::EMERGENCY->getConsoleColor())->toBe(ConsoleColor::BLACK_ON_YELLOW);
        });
    });

    describe('fromValue()', function () {
        it('returns DEBUG for value 100', function () {
            expect(LogLevel::fromValue(100))->toBe(LogLevel::DEBUG);
        });

        it('returns INFO for value 200', function () {
            expect(LogLevel::fromValue(200))->toBe(LogLevel::INFO);
        });

        it('returns NOTICE for value 250', function () {
            expect(LogLevel::fromValue(250))->toBe(LogLevel::NOTICE);
        });

        it('returns WARNING for value 300', function () {
            expect(LogLevel::fromValue(300))->toBe(LogLevel::WARNING);
        });

        it('returns ERROR for value 400', function () {
            expect(LogLevel::fromValue(400))->toBe(LogLevel::ERROR);
        });

        it('returns CRITICAL for value 500', function () {
            expect(LogLevel::fromValue(500))->toBe(LogLevel::CRITICAL);
        });

        it('returns ALERT for value 550', function () {
            expect(LogLevel::fromValue(550))->toBe(LogLevel::ALERT);
        });

        it('returns EMERGENCY for value 600', function () {
            expect(LogLevel::fromValue(600))->toBe(LogLevel::EMERGENCY);
        });

        it('returns EMERGENCY for values >= 600', function () {
            expect(LogLevel::fromValue(700))->toBe(LogLevel::EMERGENCY);
            expect(LogLevel::fromValue(1000))->toBe(LogLevel::EMERGENCY);
        });

        it('returns DEBUG for values < 100', function () {
            expect(LogLevel::fromValue(0))->toBe(LogLevel::DEBUG);
            expect(LogLevel::fromValue(50))->toBe(LogLevel::DEBUG);
        });

        it('returns next lower level for intermediate values', function () {
            expect(LogLevel::fromValue(150))->toBe(LogLevel::DEBUG);
            expect(LogLevel::fromValue(225))->toBe(LogLevel::INFO);
            expect(LogLevel::fromValue(275))->toBe(LogLevel::NOTICE);
            expect(LogLevel::fromValue(350))->toBe(LogLevel::WARNING);
            expect(LogLevel::fromValue(450))->toBe(LogLevel::ERROR);
            expect(LogLevel::fromValue(525))->toBe(LogLevel::CRITICAL);
            expect(LogLevel::fromValue(575))->toBe(LogLevel::ALERT);
        });
    });

    describe('isHigherThan()', function () {
        it('returns true when level is higher', function () {
            expect(LogLevel::ERROR->isHigherThan(LogLevel::WARNING))->toBeTrue();
            expect(LogLevel::CRITICAL->isHigherThan(LogLevel::ERROR))->toBeTrue();
            expect(LogLevel::EMERGENCY->isHigherThan(LogLevel::DEBUG))->toBeTrue();
        });

        it('returns false when level is lower', function () {
            expect(LogLevel::DEBUG->isHigherThan(LogLevel::INFO))->toBeFalse();
            expect(LogLevel::WARNING->isHigherThan(LogLevel::ERROR))->toBeFalse();
        });

        it('returns false when levels are equal', function () {
            expect(LogLevel::INFO->isHigherThan(LogLevel::INFO))->toBeFalse();
            expect(LogLevel::ERROR->isHigherThan(LogLevel::ERROR))->toBeFalse();
        });
    });

    describe('isLowerThan()', function () {
        it('returns true when level is lower', function () {
            expect(LogLevel::DEBUG->isLowerThan(LogLevel::INFO))->toBeTrue();
            expect(LogLevel::WARNING->isLowerThan(LogLevel::ERROR))->toBeTrue();
            expect(LogLevel::INFO->isLowerThan(LogLevel::EMERGENCY))->toBeTrue();
        });

        it('returns false when level is higher', function () {
            expect(LogLevel::ERROR->isLowerThan(LogLevel::WARNING))->toBeFalse();
            expect(LogLevel::CRITICAL->isLowerThan(LogLevel::ERROR))->toBeFalse();
        });

        it('returns false when levels are equal', function () {
            expect(LogLevel::INFO->isLowerThan(LogLevel::INFO))->toBeFalse();
            expect(LogLevel::ERROR->isLowerThan(LogLevel::ERROR))->toBeFalse();
        });
    });

    describe('isEqual()', function () {
        it('returns true when levels are equal', function () {
            expect(LogLevel::DEBUG->isEqual(LogLevel::DEBUG))->toBeTrue();
            expect(LogLevel::INFO->isEqual(LogLevel::INFO))->toBeTrue();
            expect(LogLevel::ERROR->isEqual(LogLevel::ERROR))->toBeTrue();
            expect(LogLevel::EMERGENCY->isEqual(LogLevel::EMERGENCY))->toBeTrue();
        });

        it('returns false when levels are different', function () {
            expect(LogLevel::DEBUG->isEqual(LogLevel::INFO))->toBeFalse();
            expect(LogLevel::ERROR->isEqual(LogLevel::WARNING))->toBeFalse();
            expect(LogLevel::CRITICAL->isEqual(LogLevel::EMERGENCY))->toBeFalse();
        });
    });

    describe('toRFC5424()', function () {
        it('returns 7 for DEBUG (RFC 5424)', function () {
            expect(LogLevel::DEBUG->toRFC5424())->toBe(7);
        });

        it('returns 6 for INFO (RFC 5424)', function () {
            expect(LogLevel::INFO->toRFC5424())->toBe(6);
        });

        it('returns 5 for NOTICE (RFC 5424)', function () {
            expect(LogLevel::NOTICE->toRFC5424())->toBe(5);
        });

        it('returns 4 for WARNING (RFC 5424)', function () {
            expect(LogLevel::WARNING->toRFC5424())->toBe(4);
        });

        it('returns 3 for ERROR (RFC 5424)', function () {
            expect(LogLevel::ERROR->toRFC5424())->toBe(3);
        });

        it('returns 2 for CRITICAL (RFC 5424)', function () {
            expect(LogLevel::CRITICAL->toRFC5424())->toBe(2);
        });

        it('returns 1 for ALERT (RFC 5424)', function () {
            expect(LogLevel::ALERT->toRFC5424())->toBe(1);
        });

        it('returns 0 for EMERGENCY (RFC 5424)', function () {
            expect(LogLevel::EMERGENCY->toRFC5424())->toBe(0);
        });
    });

    describe('value property', function () {
        it('has correct values for all log levels', function () {
            expect(LogLevel::DEBUG->value)->toBe(100);
            expect(LogLevel::INFO->value)->toBe(200);
            expect(LogLevel::NOTICE->value)->toBe(250);
            expect(LogLevel::WARNING->value)->toBe(300);
            expect(LogLevel::ERROR->value)->toBe(400);
            expect(LogLevel::CRITICAL->value)->toBe(500);
            expect(LogLevel::ALERT->value)->toBe(550);
            expect(LogLevel::EMERGENCY->value)->toBe(600);
        });
    });
});
