<?php

namespace App\Provisioning\Steps\Host;

use App\Models\Host;
use App\Models\ProvisioningRun;
use App\Provisioning\Contracts\ProvisioningStep;
use App\Provisioning\Steps\ManagesRunResources;
use App\Services\Secrets\SecretVault;
use App\Services\Ssh\RemoteShell;

/**
 * Shared helpers for host-onboarding steps: subject resolution, key login, and
 * idempotency breadcrumbs (run_resources).
 */
abstract class HostStep implements ProvisioningStep
{
    use ManagesRunResources;

    public function label(): string
    {
        return 'hosts.step.'.$this->key();
    }

    public function maxDuration(): int
    {
        return 300;
    }

    protected function host(ProvisioningRun $run): Host
    {
        /** @var Host $host */
        $host = $run->subject;

        return $host;
    }

    /**
     * Prefer the WireGuard management address once the tunnel exists, so every
     * step after ConfigureWireguard — and every later maintenance run — reaches
     * the host over the tunnel rather than its public IP. Falls back to
     * public_ip for the handful of steps that run before wg_ip is set (the
     * tunnel cannot carry SSH before it exists).
     */
    protected function keyLogin(RemoteShell $shell, Host $host): void
    {
        // The identity in force: the one stored in the console if there is
        // one, else CLUPILOT_SSH_PRIVATE_KEY(_PATH) — read here, at the
        // point of use, per SecretVault's docblock (rule 3).
        $shell->connectWithKey(
            filled($host->wg_ip) ? $host->wg_ip : $host->public_ip,
            'root',
            (string) app(SecretVault::class)->get('ssh.private_key'),
            $host->ssh_host_key, // pinned during EstablishSshTrust
        );
    }
}
