<?php declare(strict_types=1);

namespace App\Services\GenerateTokenCommand;

use App\Contracts\GenerateTokenCommand as GenerateTokenCommandContract;
use App\Exceptions\Service\GenerateTokenCommandException;
use Illuminate\Database\Eloquent\Builder;

abstract readonly class GenerateTokenCommand implements GenerateTokenCommandContract
{
    /**
     * @return string
     */
    abstract public function execute(): string;

    /**
     * @param Builder $builder
     * @param string $field
     * @param int $numberAttempts
     * @return string
     * @throws GenerateTokenCommandException
     */
    public function unique(Builder $builder, string $field, int $numberAttempts = 10): string
    {
        for ($attempt = 0; $attempt < $numberAttempts; ++$attempt) {
            $token = $this->execute();
            if ($builder->where($field, '=', $token)->doesntExist()) {
                return $token;
            }
        }

        throw new GenerateTokenCommandException(__('Failed to generate token.'));
    }
}
