<?php

declare(strict_types=1);

namespace Tests\Integration;

use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\LogChannel;
use App\Framework\Logging\LogLevel;
use App\Framework\Logging\ProcessorManager;
use App\Framework\Logging\Processors\ExceptionEnrichmentProcessor;
use App\Framework\Logging\ValueObjects\LogContext;
use Exception;
use RuntimeException;

/**
 * Integration test demonstrating Exception Enrichment Processor usage
 */
it('demonstrates exception enrichment in real logging scenario', function () {
    // Setup logger with exception processor
    $processorManager = new ProcessorManager();
    $processorManager = $processorManager->addProcessor(new ExceptionEnrichmentProcessor());

    $handler = new class () implements \App\Framework\Logging\LogHandler {
        public array $handledRecords = [];

        public function isHandling(\App\Framework\Logging\LogRecord $record): bool
        {
            return true;
        }

        public function handle(\App\Framework\Logging\LogRecord $record): void
        {
            $this->handledRecords[] = $record;
        }
    };

    $logger = new DefaultLogger(
        minLevel: LogLevel::DEBUG,
        handlers: [$handler],
        processorManager: $processorManager
    );

    // Simulate real application scenario with nested exceptions
    try {
        try {
            throw new RuntimeException('Database connection failed');
        } catch (RuntimeException $e) {
            throw new Exception('User registration failed', 500, $e);
        }
    } catch (Exception $exception) {
        // Log the exception with context
        $context = LogContext::withData([
            'user_email' => 'test@example.com',
            'action' => 'registration',
            'exception' => $exception,
        ])->addTags('error', 'registration');

        $logger->error('User registration failed with exception', $context);
    }

    // Verify enrichment worked
    expect($handler->handledRecords)->toHaveCount(1);

    $record = $handler->handledRecords[0];
    $extras = $record->getExtras();


    // Verify basic exception info
    expect($extras['exception_class'])->toBe(Exception::class);
    expect($extras['exception_message'])->toBe('User registration failed');
    expect($extras['exception_code'])->toBe(500);
    expect($extras['exception_severity'])->toBe('unknown');

    // Verify stack trace
    expect($extras['stack_trace'])->toBeArray();
    expect($extras['stack_trace_short'])->toBeString();

    // Verify previous exceptions
    expect($extras['previous_exceptions'])->toBeArray();
    expect($extras['previous_exceptions'])->toHaveCount(1);
    expect($extras['previous_exceptions'][0]['class'])->toBe(RuntimeException::class);
    expect($extras['previous_exceptions'][0]['message'])->toBe('Database connection failed');

    // Verify exception hash for grouping
    expect($extras['exception_hash'])->toBeString();
    expect($extras['exception_hash'])->toHaveLength(8);

    echo "\n🎉 Exception Enrichment Working! Enhanced exception details:\n";
    echo "  Exception: {$extras['exception_class']}\n";
    echo "  Severity: {$extras['exception_severity']}\n";
    echo "  Hash: {$extras['exception_hash']}\n";
    echo "  Previous: " . count($extras['previous_exceptions']) . " exception(s)\n";
    echo "  Short trace: {$extras['stack_trace_short']}\n";
});

/**
 * Demonstrates processor integration with channel logging
 */
it('enriches exceptions in channel logging', function () {
    $processorManager = new ProcessorManager();
    $processorManager = $processorManager->addProcessor(new ExceptionEnrichmentProcessor());

    $handler = new class () implements \App\Framework\Logging\LogHandler {
        public array $handledRecords = [];

        public function isHandling(\App\Framework\Logging\LogRecord $record): bool
        {
            return true;
        }

        public function handle(\App\Framework\Logging\LogRecord $record): void
        {
            $this->handledRecords[] = $record;
        }
    };

    $logger = new DefaultLogger(
        handlers: [$handler],
        processorManager: $processorManager
    );

    // Use security channel with exception
    $securityException = new RuntimeException('Authentication failed');
    $context = LogContext::withData([
        'ip_address' => '192.168.1.100',
        'user_agent' => 'Mozilla/5.0...',
        'exception' => $securityException,
    ])->addTags('security', 'auth_failure');

    $logger->channel(LogChannel::SECURITY)->warning('Security breach detected', $context);

    // Verify channel and enrichment
    $record = $handler->handledRecords[0];

    expect($record->getChannel())->toBe('security');
    expect($record->getExtra('exception_class'))->toBe(RuntimeException::class);
    expect($record->getExtra('exception_severity'))->toBe('medium');
});
