<?php

use App\Mail\Transport\MailboxTransport;
use App\Models\Mailbox;
use App\Services\Mail\MailPurpose;
use App\Support\MailDelivery;
use App\Support\Readiness\DeliveryChecks;
use App\Support\Settings;

/**
 * Warum die „Passwort vergessen"-Mail nicht ankam, obwohl die Zustellung
 * eingeschaltet war.
 *
 * Die Kette, im Code nachgelesen:
 *
 *   User::sendPasswordResetNotification → ResetPasswordMail (ShouldQueue)
 *     → Warteschlange → MailboxTransport('system')
 *     → MailboxResolver::for('system') liefert null
 *     → delegate() WIRFT „No configured mailbox for mail purpose [system]"
 *     → der Auftrag scheitert und landet in `failed_jobs`
 *
 * Und niemand erfährt davon: `RecordSentMail` hört auf `MessageSent`, also auf
 * das, was den Server VERLASSEN hat — ein Wurf davor hinterlässt keine Zeile im
 * Postausgang. Das Portal hat dem Kunden längst „sehen Sie in Ihr Postfach"
 * gesagt.
 *
 * Die Bereitschaftsseite hätte das melden müssen und tat es nicht: sie fragte
 * `Mailbox::query()->exists()` — ob IRGENDEIN Postfach angelegt ist. Das ist
 * nicht die Frage, an der das Senden hängt.
 */
beforeEach(function () {
    Settings::set(MailDelivery::SETTING, MailDelivery::DELIVERING);
    Mailbox::query()->delete();
    Settings::forget(MailPurpose::settingKey(MailPurpose::SYSTEM));
});

function systemCheckSatisfied(): bool
{
    foreach (DeliveryChecks::all() as $check) {
        if ($check->key === 'delivery.mailbox') {
            return $check->satisfied;
        }
    }

    throw new RuntimeException('delivery.mailbox check is gone');
}

it('is not satisfied by a mailbox that no purpose points at', function () {
    // Genau der gemeldete Zustand: ein Postfach ist angelegt, die Seite ist
    // gruen, und jede Systemmail stirbt trotzdem in der Warteschlange.
    Mailbox::factory()->create(['key' => 'irgendwas', 'active' => true]);

    expect(systemCheckSatisfied())->toBeFalse();
});

it('is not satisfied when the system purpose points at an inactive mailbox', function () {
    $box = Mailbox::factory()->create(['key' => 'system', 'active' => false]);
    Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), $box->key);

    expect(systemCheckSatisfied())->toBeFalse();
});

it('is not satisfied when the mailbox authenticates but carries no password', function () {
    $box = Mailbox::factory()->create([
        'key' => 'system', 'active' => true, 'authenticates' => true, 'password' => null,
    ]);
    Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), $box->key);

    expect(systemCheckSatisfied())->toBeFalse();
});

it('is satisfied by a mailbox the transport would actually use', function () {
    $box = Mailbox::factory()->create([
        'key' => 'system', 'active' => true, 'authenticates' => false,
    ]);
    Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), $box->key);

    expect(systemCheckSatisfied())->toBeTrue();
});

it('agrees with the transport, which is the whole point', function () {
    // Zwei Stellen, die dieselbe Frage verschieden beantworten, sind der Weg,
    // auf dem sie auseinanderlaufen — dieses Projekt hat das mehrfach bezahlt.
    // Der Test haelt die zwei aneinander, nicht jede an eine eigene Meinung.
    Mailbox::factory()->create(['key' => 'irgendwas', 'active' => true]);

    expect(systemCheckSatisfied())->toBeFalse()
        ->and((string) new MailboxTransport(MailPurpose::SYSTEM))->toContain('unconfigured');

    $box = Mailbox::factory()->create([
        'key' => 'system', 'active' => true, 'authenticates' => false,
    ]);
    Settings::set(MailPurpose::settingKey(MailPurpose::SYSTEM), $box->key);

    expect(systemCheckSatisfied())->toBeTrue()
        ->and((string) new MailboxTransport(MailPurpose::SYSTEM))->not->toContain('unconfigured');
});
