<?php
declare(strict_types=1);

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

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

final class WorkerPoolRecord
{
    public function __construct(
        private readonly string $id,
        private readonly string $name,
        private readonly string $state = WorkerPoolState::IDLE,
        private readonly int $capacity = 1,
        private readonly int $activeJobs = 0,
        private readonly array $metadata = []
    ) {}

    public static function fromWorker(WorkerInterface $worker, int $capacity = 1, array $metadata = []): self
    {
        return new self($worker->id(), $worker->name(), WorkerPoolState::IDLE, $capacity, 0, $metadata);
    }

    public static function fromArray(array $data): self
    {
        return new self(
            (string) ($data['id'] ?? ''),
            (string) ($data['name'] ?? 'worker'),
            (string) ($data['state'] ?? WorkerPoolState::IDLE),
            (int) ($data['capacity'] ?? 1),
            (int) ($data['activeJobs'] ?? 0),
            (array) ($data['metadata'] ?? [])
        );
    }

    public function id(): string { return $this->id; }
    public function name(): string { return $this->name; }
    public function state(): string { return $this->state; }
    public function capacity(): int { return $this->capacity; }
    public function activeJobs(): int { return $this->activeJobs; }
    public function available(): bool { return $this->state === WorkerPoolState::IDLE && $this->activeJobs < $this->capacity; }

    public function acquire(): self
    {
        $jobs = min($this->capacity, $this->activeJobs + 1);
        return new self($this->id, $this->name, $jobs >= $this->capacity ? WorkerPoolState::BUSY : WorkerPoolState::IDLE, $this->capacity, $jobs, $this->metadata);
    }

    public function release(): self
    {
        $jobs = max(0, $this->activeJobs - 1);
        return new self($this->id, $this->name, $jobs > 0 ? WorkerPoolState::BUSY : WorkerPoolState::IDLE, $this->capacity, $jobs, $this->metadata);
    }

    public function stop(): self
    {
        return new self($this->id, $this->name, WorkerPoolState::STOPPED, $this->capacity, $this->activeJobs, $this->metadata);
    }

    public function fail(): self
    {
        return new self($this->id, $this->name, WorkerPoolState::FAILED, $this->capacity, $this->activeJobs, $this->metadata);
    }

    public function worker(): WorkerInterface
    {
        return new DispatcherWorkerAdapter($this->id, $this->name);
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'state' => $this->state,
            'capacity' => $this->capacity,
            'activeJobs' => $this->activeJobs,
            'available' => $this->available(),
            'metadata' => $this->metadata,
        ];
    }
}
