<?php
declare(strict_types=1);

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

use PpPhp\Core\Platform\Event\Sourcing\EventStore\EventStoreRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Projection\ProjectionDefinition;
use PpPhp\Core\Platform\Event\Sourcing\Projection\ProjectionRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Query\QueryRequest;
use PpPhp\Core\Platform\Event\Sourcing\Query\QueryRuntime;
use PpPhp\Core\Platform\Event\Sourcing\Query\ReadModelDefinition;

final class QueryRuntimeVerifier
{
    public function verify(string $basePath): array
    {
        $eventStore = EventStoreRuntime::resetInstance($basePath);
        $eventStore->clear();
        $eventStore->append('query-order-1', 'Order', 'OrderCreated', ['status' => 'created', 'amount' => 100]);
        $eventStore->append('query-order-2', 'Order', 'OrderCreated', ['status' => 'created', 'amount' => 200]);
        $eventStore->append('query-order-2', 'Order', 'OrderPaid', ['status' => 'paid']);

        $projectionRuntime = ProjectionRuntime::resetInstance($basePath);
        $projectionRuntime->clear();
        $projectionRuntime->register(ProjectionDefinition::create('query_orders_projection', 'Query Orders Projection', ['Order'], []));
        $projectionRuntime->rebuild('query_orders_projection');

        $queryRuntime = QueryRuntime::resetInstance($basePath);
        $queryRuntime->clear();

        $definition = $queryRuntime->register(ReadModelDefinition::create(
            'orders_read_model_query',
            'query_orders_projection',
            'Orders Query Read Model',
            ['aggregateId', 'state.status', 'state.amount']
        ));

        $all = $queryRuntime->query(QueryRequest::create('orders_read_model_query', [], 'aggregateId', 'asc', 1, 10));
        $filtered = $queryRuntime->query(QueryRequest::create('orders_read_model_query', ['state.status' => 'paid'], 'aggregateId', 'asc', 1, 10));
        $found = $queryRuntime->find('orders_read_model_query', 'query-order-2');

        $queryRuntime->save();

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

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

        $checks = [
            'register' => $definition->readModelId() === 'orders_read_model_query',
            'query' => $all->total() === 2 && $all->returned() === 2,
            'filter' => $filtered->total() === 1 && $filtered->returned() === 1,
            'find' => is_array($found) && (($found['aggregateId'] ?? '') === 'query-order-2'),
            'statistics' => ($stats['readModels'] ?? 0) === 1 && ($stats['queries'] ?? 0) === 3,
            'persistence' => $second->store()->exists(),
            'hydration' => count($summary['results']) === 3,
        ];

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

        return [
            'ok' => !in_array(false, $checks, true),
            'checks' => $checks,
            'issues' => $issues,
            'summary' => [
                'readModels' => $stats['readModels'] ?? 0,
                'queries' => $stats['queries'] ?? 0,
                'returnedRows' => $stats['returnedRows'] ?? 0,
                'score' => in_array(false, $checks, true) ? 80 : 100,
            ],
        ];
    }
}
