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

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

/**
 * Das gemeinsame Versandkonto ausfüllen — so, wie der Betreiber es in der
 * Konsole täte.
 *
 * Die ZEILE legt eine eigene Wanderung an, inaktiv und ohne Zugangsdaten
 * (siehe InstanceRelaySeedMigrationTest). Ein `Mailbox::factory()->create()`
 * mit demselben Schlüssel liefe deshalb in die Eindeutigkeit der Spalte —
 * und das ist auch der ehrlichere Ablauf: ausgefüllt wird hier, angelegt
 * wurde dort.
 */
function versandkonto(array $werte): Mailbox
{
    $box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);
    $box->update($werte);

    return $box;
}

function versandbereit(): void
{
    Settings::set('mail.host', 'mail.clupilot.cloud');
    Settings::set('mail.port', 587);
    Settings::set('mail.encryption', 'tls');

    versandkonto([
        'address' => 'noreply@clupilot.cloud',
        'username' => 'noreply@clupilot.cloud',
        'password' => 'geheim',
        'active' => true,
        'authenticates' => true,
    ]);
}

it('baut die Werte aus Server UND Postfach zusammen', function () {
    versandbereit();
    // Instance kennt kein 'name'-Feld (siehe Migration) — GuestMailConfig
    // liest ohnehin nur das Postfach, nicht die Instanz selbst.
    $instance = Instance::factory()->create();

    $config = GuestMailConfig::for($instance);

    expect($config->available())->toBeTrue()
        ->and($config->values())->toMatchArray([
            'mail_smtpmode' => 'smtp',
            'mail_smtphost' => 'mail.clupilot.cloud',
            'mail_smtpport' => '587',
            'mail_smtpsecure' => 'tls',
            'mail_smtpauth' => 'true',
            'mail_smtpname' => 'noreply@clupilot.cloud',
            'mail_from_address' => 'noreply',
            'mail_domain' => 'clupilot.cloud',
        ])
        ->and($config->password())->toBe('geheim');
});

it('schreibt mail_smtpauth false für ein Postfach ohne Anmeldung', function () {
    // Ein Relay ohne Anmeldung ist bei Mailbox::isConfigured() ausdrücklich
    // erlaubt und verlangt kein Passwort. Ein fest verdrahtetes 'true' würde
    // Nextcloud trotzdem zur Anmeldung mit leerem Passwort zwingen und jeden
    // Versand still scheitern lassen — genau das darf hier nicht passieren.
    Settings::set('mail.host', 'mail.clupilot.cloud');
    Settings::set('mail.port', 587);
    Settings::set('mail.encryption', 'tls');

    versandkonto([
        'address' => 'noreply@clupilot.cloud',
        'password' => null,
        'active' => true,
        'authenticates' => false,
    ]);

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

    expect($config->available())->toBeTrue()
        ->and($config->values())->toMatchArray(['mail_smtpauth' => 'false']);
});

it('trägt das Passwort NICHT unter values()', function () {
    // values() wandert in Befehle. Das Passwort geht einen eigenen Weg, damit
    // niemand es versehentlich mit den übrigen Werten mitschleift.
    versandbereit();

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

    expect($values)->not->toHaveKey('mail_smtppassword')
        // Der Schlüssel allein beweist nichts: ein Leck unter einem anderen
        // Namen fände der Test oben nicht. Deshalb zusätzlich nach dem WERT
        // suchen, egal unter welchem Schlüssel er sich versteckt.
        ->and($values)->not->toContain('geheim');
});

it('sagt ohne Mailserver, dass nichts geschrieben werden darf', function () {
    versandkonto(['address' => 'noreply@clupilot.cloud', 'password' => 'geheim', 'active' => true]);
    Settings::set('mail.host', '');

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

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

it('sagt ohne Absenderpostfach, dass nichts geschrieben werden darf', function () {
    // Die Zeile GIBT es seit der eigenen Wanderung — inaktiv und ohne
    // Zugangsdaten. Genau das muss hier immer noch „kein Postfach" heissen:
    // ein Datensatz allein ist kein eingerichteter Versand.
    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('weist ein Postfach ohne Zugangsdaten ab', function () {
    Settings::set('mail.host', 'mail.clupilot.cloud');
    Settings::set('mail.port', 587);
    versandkonto(['address' => 'noreply@clupilot.cloud', 'password' => null, 'active' => true, 'authenticates' => true]);

    expect(GuestMailConfig::for(Instance::factory()->create())->problem())->toBe('no_mailbox');
});
