<?php

declare(strict_types=1);

namespace apexl\Io\modules\jobs\Service;

use apexl\Config\ConfigurationInterface;
use apexl\Io\modules\jobs\Interface\QueuedTaskFinderInterface;
use Throwable;

final readonly class TaskRunnerService
{
    public function __construct(
        private QueuedTaskFinderInterface $queuedTaskFinder,
        private ConfigurationInterface $config,
    ) {}

    public function run(?int $limit = 10): void
    {
        $batches = $this->queuedTaskFinder->tasks($limit);
        logger('queue')->debug('Starting tasks');
        foreach ($batches as $ix => $tasks) {
            logger('queue')->debug('Starting batch {batch}...', [
                'batch' => $ix,
            ]);
            foreach ($tasks as $task) {
                try {
                    if ($task->isLocked()) {
                        return;
                    }
                    $task->lock();
                    logger('queue')->info('Starting {task}', [
                        'task' => $task->name(),
                    ]);
                    $task->run();
                    logger('queue')->info('Completed {task}', [
                        'task' => $task->name(),
                    ]);
                    if ($this->config->get('jobs.retain_processed_jobs')) {
                        $task->markProcessed();
                        $task->unlock();
                    } else {
                        $task->delete();
                    }
                } catch (Throwable $throwable) {
                    logger('queue')->error('Error running {task}: {error}', [
                        'task' => $task->name(),
                        'error' => $throwable->getMessage(),
                        'exception' => $throwable,
                    ]);
                    $task->handleFailure($task->name(), $throwable);
                    $task->unlock();
                }
            }
            logger('queue')->debug('Completed batch {batch}...', [
                'batch' => $ix,
            ]);
        }
        logger('queue')->debug('Completed all requested tasks');
    }
}
