<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Distributed;

final class DistributedWorkerRecord
{
    public const ACTIVE = 'active';
    public const IDLE = 'idle';
    public const BUSY = 'busy';
    public const OFFLINE = 'offline';

    public function __construct(
        private readonly string $nodeId,
        private readonly string $workerId,
        private readonly string $status = self::IDLE,
        private readonly int $capacity = 1,
        private readonly int $activeJobs = 0,
        private readonly string $host = '',
        private readonly int $pid = 0,
        private readonly string $registeredAt = '',
        private readonly string $lastSeenAt = ''
    ) {}

    public static function register(string $nodeId, string $workerId, string $status = self::IDLE, int $capacity = 1): self
    {
        return new self(
            $nodeId,
            $workerId,
            $status,
            max(1, $capacity),
            0,
            (string) gethostname(),
            function_exists('getmypid') ? (int) getmypid() : 0,
            date('c'),
            date('c')
        );
    }

    public static function fromArray(array $data): self
    {
        return new self(
            (string) ($data['nodeId'] ?? ''),
            (string) ($data['workerId'] ?? ''),
            (string) ($data['status'] ?? self::IDLE),
            (int) ($data['capacity'] ?? 1),
            (int) ($data['activeJobs'] ?? 0),
            (string) ($data['host'] ?? ''),
            (int) ($data['pid'] ?? 0),
            (string) ($data['registeredAt'] ?? ''),
            (string) ($data['lastSeenAt'] ?? '')
        );
    }

    public function nodeId(): string { return $this->nodeId; }
    public function workerId(): string { return $this->workerId; }
    public function status(): string { return $this->status; }
    public function capacity(): int { return max(1, $this->capacity); }
    public function activeJobs(): int { return max(0, $this->activeJobs); }

    public function heartbeat(string $status = self::IDLE, int $activeJobs = 0): self
    {
        return new self(
            $this->nodeId,
            $this->workerId,
            $status,
            $this->capacity(),
            max(0, $activeJobs),
            $this->host,
            $this->pid,
            $this->registeredAt,
            date('c')
        );
    }

    public function offline(): self
    {
        return $this->heartbeat(self::OFFLINE, 0);
    }

    public function toArray(): array
    {
        return [
            'nodeId' => $this->nodeId,
            'workerId' => $this->workerId,
            'status' => $this->status,
            'capacity' => $this->capacity(),
            'activeJobs' => $this->activeJobs(),
            'availableCapacity' => max(0, $this->capacity() - $this->activeJobs()),
            'host' => $this->host,
            'pid' => $this->pid,
            'registeredAt' => $this->registeredAt !== '' ? $this->registeredAt : date('c'),
            'lastSeenAt' => $this->lastSeenAt !== '' ? $this->lastSeenAt : date('c'),
        ];
    }
}
