<?php

namespace App\Core\IpAllocator\Strategies;

use App\Core\IpAllocator\AllocatorInterface;
use App\Core\IpAllocator\Exceptions\PoolExhaustedException;
use App\Models\IpAddress;
use App\Models\IpPool;
use Illuminate\Support\Facades\DB;

class RandomAllocator implements AllocatorInterface
{
    public function allocate(IpPool $pool): IpAddress
    {
        return DB::transaction(function () use ($pool) {
            $count = $pool->ipAddresses()->where('status', 'free')->count();
            if ($count === 0) {
                throw PoolExhaustedException::for($pool->id, $pool->name);
            }

            $offset = random_int(0, $count - 1);

            $ip = $pool->ipAddresses()
                ->where('status', 'free')
                ->skip($offset)
                ->lockForUpdate()
                ->first();

            $ip->update([
                'status' => 'used',
                'assigned_at' => now(),
            ]);

            return $ip->fresh();
        });
    }

    public function key(): string
    {
        return 'random';
    }
}
