<?php

declare(strict_types=1);

namespace Tests\Unit\Framework\ErrorHandling\Handlers;

use App\Framework\ErrorHandling\Handlers\ErrorHandlerPriority;
use App\Framework\ErrorHandling\Handlers\FallbackErrorHandler;
use App\Framework\Logging\Logger;

describe('FallbackErrorHandler', function () {
    beforeEach(function () {
        $this->logger = $this->createMock(Logger::class);
        $this->handler = new FallbackErrorHandler($this->logger);
    });

    it('handles any exception', function () {
        $exception = new \RuntimeException('Any error');

        expect($this->handler->canHandle($exception))->toBeTrue();
    });

    it('logs exception with full context', function () {
        $exception = new \RuntimeException('Test error');

        $this->logger
            ->expects($this->once())
            ->method('error')
            ->with('Unhandled exception', $this->callback(function ($context) use ($exception) {
                return $context instanceof \App\Framework\Logging\ValueObjects\LogContext
                    && $context->structured['exception_class'] === \RuntimeException::class
                    && $context->structured['message'] === 'Test error'
                    && isset($context->structured['file'])
                    && isset($context->structured['line'])
                    && isset($context->structured['trace']);
            }));

        $this->handler->handle($exception);
    });

    it('returns generic error message', function () {
        $exception = new \RuntimeException('Detailed error');

        $result = $this->handler->handle($exception);

        expect($result->handled)->toBeTrue();
        expect($result->message)->toBe('An unexpected error occurred');
        expect($result->isFinal)->toBeTrue();
        expect($result->statusCode)->toBe(500);
        expect($result->data['error_type'])->toBe('unhandled');
        expect($result->data['exception_class'])->toBe(\RuntimeException::class);
    });

    it('marks result as final', function () {
        $exception = new \RuntimeException('Test');

        $result = $this->handler->handle($exception);

        expect($result->isFinal)->toBeTrue();
    });

    it('has LOWEST priority', function () {
        expect($this->handler->getPriority())->toBe(ErrorHandlerPriority::LOWEST);
    });

    it('has correct name', function () {
        expect($this->handler->getName())->toBe('fallback_error_handler');
    });
});
