<?php

namespace App\Support\Ssh;

use App\Models\Server;
use phpseclib3\Net\SSH2;
use RuntimeException;

/**
 * TOFU (trust-on-first-use) host-key pinning. phpseclib verifies the key-exchange
 * signature but does NOT pin the server's host key, so a MITM presenting its own
 * valid key would be accepted. We record the host key on first connect and refuse
 * the connection on any later mismatch.
 */
trait VerifiesHostKey
{
    private function verifyHostKey(SSH2 $conn, Server $server): void
    {
        $hostKey = $conn->getServerPublicHostKey();

        if ($hostKey === false) {
            throw new RuntimeException("Host-Key von {$server->name} ({$server->ip}) nicht lesbar — Verbindung abgebrochen.");
        }

        $known = (string) ($server->ssh_host_key ?? '');

        if ($known !== '') {
            if (! hash_equals($known, $hostKey)) {
                throw new RuntimeException("Host-Key-Mismatch fuer {$server->name} ({$server->ip}) — moegliches MITM. Verbindung abgebrochen.");
            }

            return;
        }

        // Trust on first use — but ONLY pin persisted fleet servers. A transient Server (the
        // "Clusev host" built on the fly from HostCredential) must never be written to the DB:
        // saving it would spawn a junk fleet row on every request. The host is reached over the
        // local Docker gateway (host.docker.internal), which has no network path to MITM, so
        // skipping the pin there is safe.
        if ($server->exists) {
            $server->forceFill(['ssh_host_key' => $hostKey])->save();
        }
    }
}
