<?php

namespace App\Console\Commands;

use App\Jobs\RunScheduledTaskJob;
use Illuminate\Console\Command;
use Mtc\MercuryDataModels\ScheduledTask;
use Mtc\MercuryDataModels\ScheduledTaskRun;

class DispatchScheduledTasks extends Command
{
    /**
     * @var string
     */
    protected $signature = 'scheduled-tasks:dispatch';

    /**
     * @var string
     */
    protected $description = 'Dispatch every due pending scheduled task run to the queue';

    public function handle(): int
    {
        $dispatched = 0;

        ScheduledTaskRun::query()
            ->duePending()
            ->with('task')
            ->orderBy('scheduled_for')
            ->each(function (ScheduledTaskRun $run) use (&$dispatched) {
                // Pre-check as an optimisation; the runner's atomic claim is the
                // enforcement point for same-task concurrency
                $siblingRunning = ScheduledTaskRun::query()
                    ->where('scheduled_task_id', $run->scheduled_task_id)
                    ->where('status', ScheduledTaskRun::STATUS_RUNNING)
                    ->exists();

                if ($siblingRunning) {
                    if ($run->task?->overlap_policy === ScheduledTask::OVERLAP_SKIP) {
                        $run->markSkipped('Previous run of this task still running');
                    }

                    // queue policy: leave pending for a later tick
                    return;
                }

                RunScheduledTaskJob::dispatch($run);
                $dispatched++;
            });

        if ($dispatched > 0) {
            $this->info("Dispatched {$dispatched} scheduled task runs");
        }

        return self::SUCCESS;
    }
}
