<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Consumer;

final class QueueConsumerStatistics
{
    public function __construct(
        private readonly int $pending = 0,
        private readonly int $consumed = 0,
        private readonly int $acknowledged = 0,
        private readonly int $failed = 0,
        private readonly int $retried = 0,
        private readonly int $deadLettered = 0,
        private readonly int $activeWorkers = 0,
        private readonly float $dispatchTimeMs = 0.0
    ) {}

    public function withPending(int $pending): self
    {
        return new self($pending, $this->consumed, $this->acknowledged, $this->failed, $this->retried, $this->deadLettered, $this->activeWorkers, $this->dispatchTimeMs);
    }

    public function withActiveWorkers(int $activeWorkers): self
    {
        return new self($this->pending, $this->consumed, $this->acknowledged, $this->failed, $this->retried, $this->deadLettered, $activeWorkers, $this->dispatchTimeMs);
    }

    public function record(QueueConsumerResult $result, float $timeMs): self
    {
        return new self(
            $this->pending,
            $this->consumed + ($result->acknowledged() || $result->failed() ? 1 : 0),
            $this->acknowledged + ($result->acknowledged() ? 1 : 0),
            $this->failed + ($result->failed() ? 1 : 0),
            $this->retried,
            $this->deadLettered,
            $this->activeWorkers,
            $this->dispatchTimeMs + $timeMs
        );
    }

    public function toArray(): array
    {
        return [
            'pending' => $this->pending,
            'consumed' => $this->consumed,
            'acknowledged' => $this->acknowledged,
            'failed' => $this->failed,
            'retried' => $this->retried,
            'deadLettered' => $this->deadLettered,
            'activeWorkers' => $this->activeWorkers,
            'dispatchTimeMs' => round($this->dispatchTimeMs, 3),
            'averageDispatchTimeMs' => $this->consumed > 0 ? round($this->dispatchTimeMs / $this->consumed, 3) : 0,
            'throughput' => $this->dispatchTimeMs > 0 ? round(($this->consumed / $this->dispatchTimeMs) * 1000, 2) : 0,
        ];
    }
}
