<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Sourcing\Saga\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\Domain\DomainEventEnvelope;
use PpPhp\Core\Platform\Event\Sourcing\EventStore\EventStoreRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Saga\SagaDefinition;
use PpPhp\Core\Platform\Event\Sourcing\Saga\SagaRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Saga\SagaStep;

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

        $commandBus = CommandBusRuntime::resetInstance($basePath);
        $commandBus->clear();
        $commandBus->register(CommandHandlerDefinition::create('reserve_inventory_handler', 'ReserveInventory', 'InventoryReserved'));
        $commandBus->register(CommandHandlerDefinition::create('create_invoice_handler', 'CreateInvoice', 'InvoiceCreated'));

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

        $definition = $runtime->register(SagaDefinition::create('order_fulfillment_saga', 'Order Fulfillment Saga', 'OrderCreated', [
            SagaStep::create('reserve_inventory', 'ReserveInventory', 'Inventory', ['reserved' => true])->toArray(),
            SagaStep::create('create_invoice', 'CreateInvoice', 'Invoice', ['created' => true])->toArray(),
        ]));

        $event = DomainEventEnvelope::fromStoredEvent([
            'eventId' => 'evt_saga_order_created',
            'eventType' => 'OrderCreated',
            'aggregateId' => 'saga-order-1',
            'aggregateType' => 'Order',
            'sequence' => 1,
            'payload' => ['status' => 'created'],
        ]);

        $instances = $runtime->startFromEvent($event);
        $executed = $instances !== [] ? $runtime->run($instances[0]->instanceId()) : 0;
        $runtime->save();

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

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

        $checks = [
            'register' => $definition->sagaId() === 'order_fulfillment_saga',
            'start' => count($instances) === 1,
            'run' => $executed === 2,
            'complete' => ($stats['completed'] ?? 0) === 1,
            'executions' => ($stats['executions'] ?? 0) === 2 && ($stats['successfulExecutions'] ?? 0) === 2,
            'persistence' => $second->store()->exists(),
            'hydration' => count($summary['instances']) === 1,
        ];

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

        return [
            'ok' => !in_array(false, $checks, true),
            'checks' => $checks,
            'issues' => $issues,
            'summary' => [
                'sagas' => $stats['sagas'] ?? 0,
                'instances' => $stats['instances'] ?? 0,
                'completed' => $stats['completed'] ?? 0,
                'executions' => $stats['executions'] ?? 0,
                'score' => in_array(false, $checks, true) ? 80 : 100,
            ],
        ];
    }
}
