<?php

namespace App\Console\Commands;

use App\Services\Deployment\UpdateChannel;
use App\Services\Deployment\UpdateWindow;
use Illuminate\Console\Command;

/**
 * Takes an available update, inside the window, if the owner asked for that.
 *
 * It leaves exactly the same request the button leaves — same file, same agent,
 * same run. There is no second path into a deployment, because a second path is
 * a second set of rules to keep in step with the first.
 *
 * Nothing here checks whether an update already ran today. It does not need to:
 * an installation that is current has nothing available, so an operator who
 * pressed the button at four finds the five o'clock window with nothing to do.
 */
class AutoUpdate extends Command
{
    protected $signature = 'clupilot:auto-update {--force : ignore the window, for testing the wiring}';

    protected $description = 'Install an available release during the configured update window';

    public function handle(UpdateWindow $window, UpdateChannel $channel): int
    {
        if (! $window->enabled()) {
            return self::SUCCESS;
        }

        if (! $this->option('force') && ! $window->isOpen()) {
            return self::SUCCESS;
        }

        $state = $channel->state();

        // The agent has to be alive, there has to be something to install, and
        // nothing may be running. All three come from the same state the button
        // is disabled by, so the automation cannot do what an operator is
        // prevented from doing by hand.
        if (! $state['agent_seen'] || ! $state['available'] || $state['running']) {
            return self::SUCCESS;
        }

        if ($channel->request(__('admin_settings.update_by_schedule'))) {
            $this->info('Requested an update inside the window.');
        }

        return self::SUCCESS;
    }
}
