<?php
declare(strict_types=1);

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

final class DistributedLeaseCollection
{
    /** @var array<string, DistributedJobLease> */
    private array $leases = [];

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

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

        return $collection;
    }

    public function put(DistributedJobLease $lease): void
    {
        $this->leases[$lease->leaseId()] = $lease;
    }

    public function get(string $leaseId): ?DistributedJobLease
    {
        return $this->leases[$leaseId] ?? null;
    }

    public function activeForJob(string $jobId): ?DistributedJobLease
    {
        foreach ($this->leases as $lease) {
            if ($lease->jobId() === $jobId && $lease->active()) {
                return $lease;
            }
        }

        return null;
    }

    public function renew(string $leaseId, int $ttlSeconds = 60): bool
    {
        if (!isset($this->leases[$leaseId]) || !$this->leases[$leaseId]->active()) {
            return false;
        }

        $this->leases[$leaseId] = $this->leases[$leaseId]->renew($ttlSeconds);

        return true;
    }

    public function release(string $leaseId): bool
    {
        if (!isset($this->leases[$leaseId])) {
            return false;
        }

        $this->leases[$leaseId] = $this->leases[$leaseId]->release();

        return true;
    }

    public function expireDue(): int
    {
        $count = 0;

        foreach ($this->leases as $id => $lease) {
            if ($lease->status() === DistributedLeaseStatus::ACTIVE && $lease->expired()) {
                $this->leases[$id] = $lease->markExpired();
                $count++;
            }
        }

        return $count;
    }

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

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

    public function statistics(): array
    {
        $stats = [
            'leases' => count($this->leases),
            'active' => 0,
            'released' => 0,
            'expired' => 0,
            'denied' => 0,
        ];

        foreach ($this->leases as $lease) {
            $status = $lease->status();
            if (array_key_exists($status, $stats)) {
                $stats[$status]++;
            }
        }

        return $stats;
    }

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