<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Distributed\Queue;

final class DistributedQueueRegistry
{
    /** @var array<string, DistributedQueueRecord> */
    private array $queues = [];

    public static function fromArray(array $items): self
    {
        $registry = new self();

        foreach ($items as $item) {
            if (is_array($item)) {
                $registry->put(DistributedQueueRecord::fromArray($item));
            }
        }

        return $registry;
    }

    public function put(DistributedQueueRecord $record): void
    {
        $this->queues[$record->queueName()] = $record;
    }

    public function register(string $queueName, int $priority = 0): DistributedQueueRecord
    {
        $record = DistributedQueueRecord::register($queueName, $priority);
        $this->put($record);

        return $record;
    }

    public function get(string $queueName): ?DistributedQueueRecord
    {
        return $this->queues[$queueName] ?? null;
    }

    public function updateCounters(string $queueName, int $pending, int $reserved = 0): bool
    {
        if (!isset($this->queues[$queueName])) {
            return false;
        }

        $this->queues[$queueName] = $this->queues[$queueName]->withCounters($pending, $reserved);

        return true;
    }

    public function all(): array
    {
        return array_values($this->queues);
    }

    public function count(): int
    {
        return count($this->queues);
    }

    public function statistics(): array
    {
        $stats = [
            'queues' => count($this->queues),
            'active' => 0,
            'paused' => 0,
            'pending' => 0,
            'reserved' => 0,
        ];

        foreach ($this->queues as $queue) {
            $status = $queue->status();
            if ($status === DistributedQueueRecord::ACTIVE) {
                $stats['active']++;
            } elseif ($status === DistributedQueueRecord::PAUSED) {
                $stats['paused']++;
            }

            $stats['pending'] += $queue->pending();
            $stats['reserved'] += $queue->reserved();
        }

        return $stats;
    }

    public function toArray(): array
    {
        return array_map(static fn (DistributedQueueRecord $record): array => $record->toArray(), $this->all());
    }
}
