<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Sourcing\Aggregate;

use PpPhp\Core\Platform\Event\Sourcing\EventStore\EventStoreRuntime;

final class AggregateRepository
{
    public function __construct(private readonly EventStoreRuntime $eventStore) {}

    public function save(
        string $aggregateId,
        string $aggregateType,
        string $eventType,
        array $payload = [],
        array $metadata = []
    ): AggregateState {
        $this->eventStore->append($aggregateId, $aggregateType, $eventType, $payload, $metadata);

        return $this->load($aggregateId, $aggregateType);
    }

    public function load(string $aggregateId, string $aggregateType = ''): AggregateState
    {
        $events = $this->eventStore->eventsForAggregate($aggregateId);
        $type = $aggregateType;

        if ($events !== [] && $type === '') {
            $first = $events[0]->toArray();
            $type = (string) ($first['aggregateType'] ?? '');
        }

        $state = AggregateState::empty($aggregateId, $type);

        foreach ($events as $event) {
            $state = $state->apply($event->toArray());
        }

        return $state;
    }

    public function exists(string $aggregateId): bool
    {
        return count($this->eventStore->eventsForAggregate($aggregateId)) > 0;
    }

    public function history(string $aggregateId): array
    {
        return array_map(static fn ($event): array => $event->toArray(), $this->eventStore->eventsForAggregate($aggregateId));
    }
}
