<?php
declare(strict_types=1);

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

use PpPhp\Core\Platform\Event\Sourcing\Versioning\EventUpcaster;
use PpPhp\Core\Platform\Event\Sourcing\Versioning\EventVersion;
use PpPhp\Core\Platform\Event\Sourcing\Versioning\EventVersioningRuntime;

final class EventVersioningVerifier
{
    public function verify(string $basePath): array
    {
        $runtime = EventVersioningRuntime::resetInstance($basePath);
        $runtime->clear();

        $version = $runtime->registerVersion(EventVersion::create('OrderCreated', 2, 'order-created-v2'));
        $upcaster = $runtime->registerUpcaster(EventUpcaster::create('order_created_v1_to_v2', 'OrderCreated', 1, 2, ['amount' => 'total'], ['currency' => 'AUD']));

        $result = $runtime->upcast(['eventId' => 'evt_version_verify_1', 'eventType' => 'OrderCreated', 'aggregateId' => 'order-version-1', 'aggregateType' => 'Order', 'sequence' => 1, 'payload' => ['amount' => 100], 'metadata' => ['eventVersion' => 1]]);
        $unchanged = $runtime->upcast(['eventId' => 'evt_version_verify_2', 'eventType' => 'CustomerRegistered', 'aggregateId' => 'customer-version-1', 'aggregateType' => 'Customer', 'sequence' => 2, 'payload' => ['name' => 'Ada'], 'metadata' => ['eventVersion' => 1]]);

        $runtime->save();
        $second = EventVersioningRuntime::resetInstance($basePath);
        $second->hydrate();

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

        $checks = [
            'version' => $version->version() === 2,
            'upcaster' => $upcaster->fromVersion() === 1 && $upcaster->toVersion() === 2,
            'upcast' => $result->upcasted() && (($event['payload']['total'] ?? null) === 100) && (($event['payload']['currency'] ?? '') === 'AUD'),
            'unchanged' => !$unchanged->upcasted(),
            'statistics' => ($stats['versions'] ?? 0) === 1 && ($stats['upcasters'] ?? 0) === 1 && ($stats['upcasted'] ?? 0) === 1,
            'persistence' => $second->store()->exists(),
            'hydration' => count($summary['results']) === 2,
        ];

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

        return ['ok' => !in_array(false, $checks, true), 'checks' => $checks, 'issues' => $issues, 'summary' => ['versions' => $stats['versions'] ?? 0, 'upcasters' => $stats['upcasters'] ?? 0, 'results' => $stats['results'] ?? 0, 'upcasted' => $stats['upcasted'] ?? 0, 'score' => in_array(false, $checks, true) ? 80 : 100]];
    }
}
