<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Streaming\Dlq\Validation;

use PpPhp\Core\Platform\Event\Streaming\MessageBus;
use PpPhp\Core\Platform\Event\Streaming\Dlq\StreamDlqRuntime;
use PpPhp\Core\Platform\Event\Streaming\Dlq\StreamRetryPolicy;
use PpPhp\Core\Platform\Event\Streaming\Publisher\PublisherManager;

final class StreamDlqVerifier
{
    public function verify(string $basePath): array
    {
        MessageBus::resetInstance($basePath)->clear();
        PublisherManager::resetInstance($basePath)->clear();

        $runtime = StreamDlqRuntime::resetInstance($basePath, new StreamRetryPolicy(3, 1, 2.0));
        $runtime->reset();

        $dead = $runtime->deadLetter([
            'messageId' => 'msg_dlq_verify_1',
            'topic' => 'dlq.topic',
            'type' => 'dlq.failed',
            'payload' => ['id' => 1],
            'headers' => ['source' => 'verifier'],
        ], 'verification failure');

        $retry = $runtime->retry($dead->dlqId());
        $replay = $runtime->replay($dead->dlqId());

        $runtime->deadLetter([
            'messageId' => 'msg_dlq_verify_2',
            'topic' => 'dlq.topic',
            'type' => 'dlq.failed',
            'payload' => ['id' => 2],
            'headers' => [],
        ], 'second failure');

        $clear = $runtime->clear();
        $runtime->save();

        $second = StreamDlqRuntime::resetInstance($basePath);
        $second->hydrate();

        $summary = $second->summary();
        $stats = $summary['statistics'];

        /*
         * The clear operation is terminal and legitimately converts previously
         * replayed DLQ entries to CLEARED. Therefore, final message-status
         * counters may show replayed=0 and cleared=2 even when replay succeeded.
         * Verification must use the replay operation result for replay success,
         * and use final counters only for terminal-state confirmation.
         */
        $checks = [
            'deadLetter' => ($stats['messages'] ?? 0) === 2,
            'retry' => $retry->affected() === 1,
            'replay' => $replay->affected() === 1,
            'clear' => $clear->affected() >= 1,
            'statistics' => ($stats['cleared'] ?? 0) >= 1 && ($stats['successfulResults'] ?? 0) >= 4,
            'persistence' => $second->store()->exists(),
            'hydration' => count($summary['messages']) === 2,
        ];

        $issues = [];
        foreach ($checks as $check => $ok) {
            if (!$ok) {
                $issues[] = ['check' => $check, 'message' => 'DLQ verification failed: ' . $check];
            }
        }

        return [
            'ok' => !in_array(false, $checks, true),
            'checks' => $checks,
            'issues' => $issues,
            'summary' => [
                'messages' => $stats['messages'] ?? 0,
                'dead' => $stats['dead'] ?? 0,
                'retryPending' => $stats['retryPending'] ?? 0,
                'retried' => $stats['retried'] ?? 0,
                'replayed' => $stats['replayed'] ?? 0,
                'cleared' => $stats['cleared'] ?? 0,
                'successfulResults' => $stats['successfulResults'] ?? 0,
                'score' => in_array(false, $checks, true) ? 80 : 100,
            ],
        ];
    }
}
