<?php

declare(strict_types=1);

namespace Tests\Integration;

use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\Formatter\DevelopmentFormatter;
use App\Framework\Logging\Formatter\JsonFormatter;
use App\Framework\Logging\Formatter\LineFormatter;
use App\Framework\Logging\Formatter\LogFormatter;
use App\Framework\Logging\Formatter\StructuredFormatter;
use App\Framework\Logging\LogHandler;
use App\Framework\Logging\LogRecord;
use App\Framework\Logging\ProcessorManager;
use App\Framework\Logging\Processors\ExceptionEnrichmentProcessor;
use App\Framework\Logging\ValueObjects\LogContext;
use Exception;
use RuntimeException;

/**
 * Integration test demonstrating Formatter usage with handlers
 */

// Enhanced handler that supports formatters
class FormattableHandler implements LogHandler
{
    public array $handledOutputs = [];

    public function __construct(
        private readonly ?LogFormatter $formatter = null
    ) {
    }

    public function isHandling(LogRecord $record): bool
    {
        return true;
    }

    public function handle(LogRecord $record): void
    {
        if ($this->formatter) {
            $output = ($this->formatter)($record);
            $this->handledOutputs[] = $output;
        } else {
            $this->handledOutputs[] = $record->getMessage();
        }
    }
}

it('demonstrates different formatters with same log data', function () {
    echo "\n🎨 Formatter Showcase:\n\n";

    // Setup exception-enriched log record
    $processorManager = new ProcessorManager();
    $processorManager = $processorManager->addProcessor(new ExceptionEnrichmentProcessor());

    try {
        throw new RuntimeException('Database connection timeout');
    } catch (RuntimeException $e) {
        $exception = new Exception('User operation failed', 500, $e);

        $context = LogContext::withData([
            'user_id' => 12345,
            'operation' => 'create_order',
            'request_id' => 'req_abc123',
            'exception' => $exception,
        ])->addTags('error', 'order_processing');

        // Create handlers with different formatters
        $lineHandler = new FormattableHandler(new LineFormatter());
        $jsonHandler = new FormattableHandler(new JsonFormatter());
        $devHandler = new FormattableHandler(new DevelopmentFormatter(colorOutput: false));
        $structuredHandler = new FormattableHandler(new StructuredFormatter());

        $logger = new DefaultLogger(
            handlers: [$lineHandler, $jsonHandler, $devHandler, $structuredHandler],
            processorManager: $processorManager
        );

        $logger->error('Order creation failed due to database issues', $context);

        // Display different formatter outputs
        echo "1. LINE FORMAT:\n";
        echo $lineHandler->handledOutputs[0] . "\n\n";

        echo "2. JSON FORMAT:\n";
        echo $jsonHandler->handledOutputs[0] . "\n\n";

        echo "3. DEVELOPMENT FORMAT:\n";
        echo $devHandler->handledOutputs[0] . "\n";

        echo "4. STRUCTURED FORMAT (logfmt):\n";
        echo $structuredHandler->handledOutputs[0] . "\n\n";

        // Verify all handlers received the log
        expect($lineHandler->handledOutputs)->toHaveCount(1);
        expect($jsonHandler->handledOutputs)->toHaveCount(1);
        expect($devHandler->handledOutputs)->toHaveCount(1);
        expect($structuredHandler->handledOutputs)->toHaveCount(1);

        // Verify JSON is valid
        $jsonData = json_decode($jsonHandler->handledOutputs[0], true);
        expect($jsonData)->toBeArray();
        expect($jsonData['extra']['exception_class'])->toBe(Exception::class);
    }
});

it('demonstrates formatter customization options', function () {
    echo "\n⚙️  Formatter Customization:\n\n";

    $context = LogContext::withData(['api_key' => 'sk_test_123', 'response_time' => 245]);

    // Custom line format
    $customLineFormatter = new LineFormatter(
        format: "{timestamp} | {level} | {message}",
        timestampFormat: 'H:i:s'
    );

    // Pretty JSON
    $prettyJsonFormatter = new JsonFormatter(prettyPrint: true);

    // Structured as key-value
    $kvFormatter = new StructuredFormatter(format: 'kv');

    $handlers = [
        'custom_line' => new FormattableHandler($customLineFormatter),
        'pretty_json' => new FormattableHandler($prettyJsonFormatter),
        'key_value' => new FormattableHandler($kvFormatter),
    ];

    $logger = new DefaultLogger(handlers: array_values($handlers));
    $logger->info('API request completed successfully', $context);

    echo "CUSTOM LINE FORMAT:\n";
    echo $handlers['custom_line']->handledOutputs[0] . "\n\n";

    echo "PRETTY JSON FORMAT:\n";
    echo $handlers['pretty_json']->handledOutputs[0] . "\n\n";

    echo "KEY-VALUE FORMAT:\n";
    echo $handlers['key_value']->handledOutputs[0] . "\n\n";

    // Verify customizations
    expect($handlers['custom_line']->handledOutputs[0])->toContain(' | INFO | ');
    expect($handlers['pretty_json']->handledOutputs[0])->toContain('    '); // Pretty print spacing
    expect($handlers['key_value']->handledOutputs[0])->toContain('level: INFO');
});

it('demonstrates formatter performance with batch logging', function () {
    $jsonFormatter = new JsonFormatter();
    $handler = new FormattableHandler($jsonFormatter);
    $logger = new DefaultLogger(handlers: [$handler]);

    // Batch log multiple entries
    for ($i = 1; $i <= 5; $i++) {
        $context = LogContext::withData(['batch_id' => "batch_$i", 'item_count' => $i * 10]);
        $logger->info("Processed batch $i", $context);
    }

    expect($handler->handledOutputs)->toHaveCount(5);

    // Verify all are valid JSON
    foreach ($handler->handledOutputs as $output) {
        $decoded = json_decode($output, true);
        expect($decoded)->toBeArray();
        expect($decoded['message'])->toContain('Processed batch');
    }

    echo "\n📊 Batch Logging Demo: " . count($handler->handledOutputs) . " entries formatted as JSON\n";
});
