<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Sourcing\Command\Validation;

use PpPhp\Core\Platform\Event\Sourcing\Aggregate\AggregateRepositoryRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Command\CommandBusRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Command\CommandHandlerDefinition;
use PpPhp\Core\Platform\Event\Sourcing\Command\CommandMessage;
use PpPhp\Core\Platform\Event\Sourcing\EventStore\EventStoreRuntime;

final class CommandBusVerifier
{
    public function verify(string $basePath): array
    {
        EventStoreRuntime::resetInstance($basePath)->clear();
        AggregateRepositoryRuntime::resetInstance($basePath)->clear();

        $runtime = CommandBusRuntime::resetInstance($basePath);
        $runtime->clear();

        $handler = $runtime->register(CommandHandlerDefinition::create('create_order_handler', 'CreateOrder', 'OrderCreated'));

        $command = CommandMessage::create('CreateOrder', 'command-order-1', 'Order', ['status' => 'created', 'amount' => 300], ['source' => 'verifier']);
        $result = $runtime->dispatch($command);

        $missing = $runtime->dispatch(CommandMessage::create('UnknownCommand', 'command-order-2', 'Order', ['status' => 'ignored']));

        $runtime->save();

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

        $aggregate = AggregateRepositoryRuntime::instance($basePath)->load('command-order-1');
        $summary = $second->summary();
        $stats = $summary['statistics'];

        $checks = [
            'register' => $handler->handlerId() === 'create_order_handler',
            'dispatch' => $result->isHandled() && $result->successful(),
            'eventCreated' => $aggregate->version() === 1 && (($aggregate->state()['status'] ?? '') === 'created'),
            'missingHandler' => !$missing->successful(),
            'statistics' => ($stats['handlers'] ?? 0) === 1 && ($stats['commands'] ?? 0) === 2 && ($stats['handled'] ?? 0) === 1 && ($stats['failed'] ?? 0) === 1,
            'persistence' => $second->store()->exists(),
            'hydration' => count($summary['results']) === 2,
        ];

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

        return [
            'ok' => !in_array(false, $checks, true),
            'checks' => $checks,
            'issues' => $issues,
            'summary' => [
                'handlers' => $stats['handlers'] ?? 0,
                'commands' => $stats['commands'] ?? 0,
                'handled' => $stats['handled'] ?? 0,
                'failed' => $stats['failed'] ?? 0,
                'score' => in_array(false, $checks, true) ? 80 : 100,
            ],
        ];
    }
}
