<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Worker\Pool;

use PpPhp\Core\Platform\Event\Worker\Contracts\WorkerInterface;

final class WorkerPool
{
    private WorkerPoolRegistry $registry;

    public function __construct(private readonly string $name = 'default')
    {
        $this->registry = new WorkerPoolRegistry();
    }

    public function name(): string { return $this->name; }
    public function registry(): WorkerPoolRegistry { return $this->registry; }

    public function register(WorkerInterface $worker, int $capacity = 1, array $metadata = []): void
    {
        $this->registry->register($worker, $capacity, $metadata);
    }

    public function remove(string $id): bool
    {
        return $this->registry->remove($id);
    }

    public function acquire(): ?WorkerPoolRecord
    {
        $available = $this->registry->available()[0] ?? null;
        if (!$available instanceof WorkerPoolRecord) {
            return null;
        }

        $acquired = $available->acquire();
        $this->registry->replace($acquired);

        return $acquired;
    }

    public function release(string $id): bool
    {
        $record = $this->registry->get($id);
        if (!$record instanceof WorkerPoolRecord) {
            return false;
        }

        $this->registry->replace($record->release());
        return true;
    }

    public function statistics(): WorkerPoolStatistics
    {
        return new WorkerPoolStatistics($this->registry->all());
    }

    public function snapshot(): WorkerPoolSnapshot
    {
        return new WorkerPoolSnapshot($this->registry->toArray(), $this->statistics()->toArray());
    }

    public function restore(WorkerPoolSnapshot $snapshot): void
    {
        $this->registry = new WorkerPoolRegistry();
        foreach ($snapshot->workers() as $worker) {
            $this->registry->addRecord(WorkerPoolRecord::fromArray($worker));
        }
    }

    public function toArray(): array
    {
        return [
            'name' => $this->name,
            'workers' => $this->registry->toArray(),
            'statistics' => $this->statistics()->toArray(),
        ];
    }
}
