<?php // tests/Feature/Mail/InstanceRelaySeedMigrationTest.php

use App\Models\Instance;
use App\Models\Mailbox;
use App\Services\Mail\GuestMailConfig;
use App\Support\Settings;

/**
 * Lädt bei jedem Aufruf eine frische Instanz der anonymen Klasse — `require`,
 * nicht `require_once`, aus demselben Grund wie in MailboxSeedMigrationTest:
 * PHP wertet den `return new class …`-Ausdruck jedes Mal neu aus, und nur so
 * lässt sich up() gegen eine Datenbank fahren, die RefreshDatabase längst
 * einmal migriert hat.
 */
function loadInstanceRelaySeedMigration(): object
{
    return require database_path('migrations/2026_08_03_190000_ein_versandkonto_fuer_die_kundeninstanzen.php');
}

it('legt das gemeinsame Versandkonto der Kundeninstanzen an', function () {
    // Ohne diesen Datensatz käme der Betreiber ohne Tinker gar nicht an den
    // Start: GuestMailConfig sucht genau diesen Schlüssel, und die Konsole
    // kann Postfächer nur bearbeiten, nicht erstellen.
    $box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);

    expect($box)->not->toBeNull()
        ->and($box->address)->toBe('noreply@clupilot.cloud');
});

it('legt es inaktiv und ohne Zugangsdaten an', function () {
    // Ein Postfach, das ohne Zutun des Betreibers als einsatzbereit dastünde,
    // wäre das nächste stille Versprechen: ConfigureInstanceMail schriebe
    // dann Werte in die Kunden-Nextcloud, die niemand je eingetragen hat.
    $box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);

    expect($box->active)->toBeFalse()
        ->and($box->getRawOriginal('password'))->toBeNull()
        ->and($box->isConfigured())->toBeFalse();
});

it('hält GuestMailConfig davon ab, halb eingetragene Werte zu liefern', function () {
    // Die Probe aufs Exempel: solange niemand das Postfach ausgefüllt hat,
    // muss `no_mailbox` herauskommen — auch jetzt, wo es die Zeile GIBT.
    Settings::set('mail.host', 'mail.clupilot.cloud');
    Settings::set('mail.port', 587);

    $config = GuestMailConfig::for(Instance::factory()->create());

    expect($config->available())->toBeFalse()
        ->and($config->problem())->toBe('no_mailbox');
});

it('ist zweimal zu laufen unbedenklich', function () {
    // `firstOrNew`, nicht `new Mailbox`: eine Wanderung, die auf halbem Weg
    // scheitert, steht nicht in der migrations-Tabelle — der zweite Lauf muss
    // die Zeile aktualisieren, nicht an der Eindeutigkeit des Schlüssels
    // abprallen.
    $threw = null;
    try {
        loadInstanceRelaySeedMigration()->up();
    } catch (Throwable $e) {
        $threw = $e;
    }

    expect($threw)->toBeNull()
        ->and(Mailbox::query()->where('key', GuestMailConfig::RELAY_KEY)->count())->toBe(1);
});

it('lässt ein bereits ausgefülltes Postfach beim zweiten Lauf in Ruhe', function () {
    // Der Fall, der wirklich weh täte: der Betreiber hat Adresse und Passwort
    // eingetragen und das Konto scharfgeschaltet, dann läuft die Wanderung
    // aus irgendeinem Grund erneut. Sie darf ihm den Versand nicht wieder
    // abschalten.
    Mailbox::findByKey(GuestMailConfig::RELAY_KEY)->update([
        'address' => 'versand@kunde.example',
        'password' => 'geheim',
        'active' => true,
    ]);

    loadInstanceRelaySeedMigration()->up();

    $box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);

    expect($box->address)->toBe('versand@kunde.example')
        ->and($box->active)->toBeTrue()
        ->and($box->password)->toBe('geheim');
});

it('nimmt beim Zurücknehmen nur das eigene Postfach mit', function () {
    loadInstanceRelaySeedMigration()->down();

    expect(Mailbox::findByKey(GuestMailConfig::RELAY_KEY))->toBeNull()
        // Die fünf Postfächer der früheren Wanderung gehören ihr, nicht
        // dieser hier.
        ->and(Mailbox::findByKey('no-reply'))->not->toBeNull();
});
