<?php

declare(strict_types=1);

namespace Apexl\Io\Jobs\Commands;

use Apexl\Io\Jobs\Services\TaskRunnerService;
use Apexl\Io\System\Commands\DaedalusCommand;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'jobs:run', description: 'Run job queue')]
class RunJobsCommand extends DaedalusCommand
{
    private const int DEFAULT_LIMIT = 10;

    public function __construct(
        private readonly TaskRunnerService $taskRunnerService
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        parent::configure();

        $this->addOption(
            'limit',
            'l',
            InputOption::VALUE_OPTIONAL,
            'The number of jobs to process',
            self::DEFAULT_LIMIT,
        );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->taskRunnerService->run($this->limit($input));

        return 0;
    }

    /**
     * Symfony hands back the *default* with the type it was declared with, but anything
     * typed on the command line as a string. So `jobs:run` worked while
     * `jobs:run --limit=100` raised a TypeError against run(?int $limit) before a single job
     * ran — which made the option look unusable and pinned every worker to the default.
     *
     * A bare `--limit` with no value gives null, which is not "unlimited": it would reach
     * QueuedTaskFinderInterface::tasks(int $limit) — not nullable — and where it does not,
     * `min(null, BATCH)` makes the loop condition false and nothing runs at all. So it means
     * the default here, same as leaving the option off.
     */
    private function limit(InputInterface $input): int
    {
        $limit = $input->getOption('limit');

        return $limit === null ? self::DEFAULT_LIMIT : (int) $limit;
    }
}
