<?php

declare(strict_types=1);

use App\Framework\Logging\LogLevel;
use App\Framework\Logging\LogRecord;
use App\Framework\Logging\Processors\RequestIdProcessor;
use App\Framework\Logging\ValueObjects\LogContext;
use App\Framework\Http\RequestIdGenerator;

describe('RequestIdProcessor', function () {
    beforeEach(function () {
        $this->timestamp = new DateTimeImmutable('2024-01-15 10:30:45', new DateTimeZone('Europe/Berlin'));
    });

    describe('constructor', function () {
        it('accepts RequestIdGenerator dependency', function () {
            $generator = new RequestIdGenerator();

            $processor = new RequestIdProcessor($generator);

            expect($processor instanceof RequestIdProcessor)->toBeTrue();
        });
    });

    describe('getPriority()', function () {
        it('returns priority 10', function () {
            $generator = new RequestIdGenerator();

            $processor = new RequestIdProcessor($generator);

            expect($processor->getPriority())->toBe(10);
        });
    });

    describe('getName()', function () {
        it('returns name request_id', function () {
            $generator = new RequestIdGenerator();

            $processor = new RequestIdProcessor($generator);

            expect($processor->getName())->toBe('request_id');
        });
    });

    describe('processRecord()', function () {
        it('returns original record when no current request ID', function () {
            $generator = new RequestIdGenerator();

            $processor = new RequestIdProcessor($generator);

            $record = new LogRecord(
                message: 'Test message',
                context: LogContext::empty(),
                level: LogLevel::INFO,
                timestamp: $this->timestamp
            );

            $processed = $processor->processRecord($record);

            expect($processed->getExtras())->toBeEmpty();
        });

        it('adds request_id extra when current ID exists', function () {
            $generator = new RequestIdGenerator();
            // Generate a request ID to make it available
            $generator->generate();

            $processor = new RequestIdProcessor($generator);

            $record = new LogRecord(
                message: 'Test message',
                context: LogContext::empty(),
                level: LogLevel::INFO,
                timestamp: $this->timestamp
            );

            $processed = $processor->processRecord($record);

            $extras = $processed->getExtras();
            expect(isset($extras['request_id']))->toBeTrue();
            expect($extras['request_id'])->toBeString();
        });

        it('does not modify existing extras', function () {
            $generator = new RequestIdGenerator();
            // Generate a request ID to make it available
            $generator->generate();

            $processor = new RequestIdProcessor($generator);

            $record = (new LogRecord(
                message: 'Test message',
                context: LogContext::empty(),
                level: LogLevel::INFO,
                timestamp: $this->timestamp
            ))->addExtra('existing_key', 'existing_value');

            $processed = $processor->processRecord($record);

            $extras = $processed->getExtras();
            expect(isset($extras['existing_key']))->toBeTrue();
            expect($extras['existing_key'])->toBe('existing_value');
            expect(isset($extras['request_id']))->toBeTrue();
        });
    });

    describe('readonly behavior', function () {
        it('is a readonly class', function () {
            $reflection = new ReflectionClass(RequestIdProcessor::class);

            expect($reflection->isReadOnly())->toBeTrue();
        });
    });
});
