<?php
declare(strict_types=1);

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

use PpPhp\Core\Platform\Event\Distributed\DistributedRuntimeCoordinator;
use PpPhp\Core\Platform\Event\Distributed\Lease\DistributedLeaseManager;

final class DistributedQueueDispatcher
{
    public function __construct(
        private readonly DistributedRuntimeCoordinator $runtime,
        private readonly DistributedLeaseManager $leases
    ) {}

    public function dispatch(string $queueName, string $jobId, int $ttlSeconds = 60): array
    {
        $workers = $this->runtime->registry()->toArray();

        usort($workers, static function (array $a, array $b): int {
            return ((int) ($b['availableCapacity'] ?? 0)) <=> ((int) ($a['availableCapacity'] ?? 0));
        });

        foreach ($workers as $worker) {
            if ((int) ($worker['availableCapacity'] ?? 0) <= 0) {
                continue;
            }

            $lease = $this->leases->acquire(
                $queueName . ':' . $jobId,
                (string) ($worker['nodeId'] ?? ''),
                (string) ($worker['workerId'] ?? ''),
                $ttlSeconds
            );

            if ($lease === null) {
                continue;
            }

            return [
                'dispatched' => true,
                'queueName' => $queueName,
                'jobId' => $jobId,
                'nodeId' => $worker['nodeId'] ?? '',
                'workerId' => $worker['workerId'] ?? '',
                'leaseId' => $lease->leaseId(),
            ];
        }

        return [
            'dispatched' => false,
            'queueName' => $queueName,
            'jobId' => $jobId,
            'reason' => 'no available worker or lease denied',
        ];
    }
}
