<?php

use App\Models\Mailbox;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

/**
 * Das Postfach, auf dem die Mitarbeiterverwaltung steht — als Zeile, die der
 * Betreiber ausfüllen kann.
 *
 * `GuestMailConfig` sucht das gemeinsame Versandkonto der Kundeninstanzen
 * unter dem Schlüssel `instance-relay`. Diesen Datensatz legte bisher
 * NIRGENDS etwas an, und die Konsole kann Postfächer nur bearbeiten, nicht
 * erstellen: der Betreiber käme ohne Tinker gar nicht an den Start.
 *
 * Und daran hängt mehr als eine Einstellung. Ohne Postfach verschickt die
 * Kunden-Nextcloud keine Mail — aber `occ user:add --generate-password
 * --email` gelingt trotzdem: Nextcloud legt das Konto an, versucht die
 * Willkommensmail, protokolliert intern einen Fehler und beendet mit 0. Das
 * Portal schriebe also „Einladung verschickt. Der Mitarbeiter bekommt einen
 * Link, an dem er sein Passwort selbst setzt", während niemand eine Mail
 * bekommt. Dieselbe Attrappe, die dieses Feature abschaffen sollte, eine
 * Schicht tiefer.
 *
 * INAKTIV und OHNE Zugangsdaten, mit Absicht: ein Postfach, das ohne Zutun des
 * Betreibers als einsatzbereit dastünde, wäre das nächste stille
 * Versprechen. So erscheint es in der Konsole als eine Zeile, die sichtbar
 * noch etwas braucht — `Mailbox::isConfigured()` bleibt `false`,
 * `GuestMailConfig` meldet `no_mailbox`, und `ConfigureInstanceMail` geht mit
 * einem sichtbaren Lauf-Ereignis weiter, statt halbe Werte in eine
 * Kundeninstanz zu schreiben.
 *
 * `firstOrNew` statt `new Mailbox`, wie bei der Wanderung, die die fünf
 * Betreiber-Postfächer anlegt: eine Wanderung, die auf halbem Weg scheitert,
 * steht nicht in der migrations-Tabelle, und der zweite Lauf muss die Zeile
 * aktualisieren statt an der Eindeutigkeit des Schlüssels abzuprallen. Er
 * darf dabei nur die Felder anfassen, die noch NIE jemand ausgefüllt hat —
 * siehe unten.
 *
 * Der Schlüssel steht hier ausgeschrieben und nicht als
 * `GuestMailConfig::RELAY_KEY`: eine Wanderung friert ein, was zum Zeitpunkt
 * ihres Schreibens galt (siehe die Begründung in der seats-Wanderung vom
 * selben Tag). Ändert die Konstante sich später, soll DIESE Zeile nicht
 * mitwandern — dann gehört eine neue Wanderung geschrieben, die den
 * Datensatz umbenennt.
 */
return new class extends Migration
{
    private const KEY = 'instance-relay';

    public function up(): void
    {
        DB::transaction(function () {
            $box = Mailbox::firstOrNew(['key' => self::KEY]);

            // Ein bestehender Datensatz wird NICHT überschrieben. Läuft die
            // Wanderung ein zweites Mal — ein Wiederholungslauf nach einem
            // Abbruch, ein `migrate` auf einem Server, der schon eines hatte —
            // hätte der Betreiber sonst Adresse, Anmeldung und Passwort neu
            // einzutragen, und bis er es merkt, verschickt keine Kundencloud
            // mehr eine Einladung. Der stillste denkbare Ausfall.
            if ($box->exists) {
                return;
            }

            $box->fill([
                'address' => 'noreply@clupilot.cloud',
                'display_name' => 'CluPilot',
                // Null heisst „Anmeldename gleich Adresse" (siehe
                // Mailbox::smtpUsername()). Die Adresse selbst steht schon
                // oben; sie hier zu wiederholen wäre eine Kopie, die nur
                // einmal auseinanderlaufen muss, um zum Fehler zu werden.
                'username' => null,
                'password' => null,
                // Auf diese Adresse antwortet niemand. Ein „noreply", dem man
                // schreiben kann, ist eine Lüge im Absender.
                'no_reply' => true,
                // Der Kern dieser Wanderung: die Zeile ist da, der Versand
                // nicht. Erst wer Adresse und Passwort einträgt und dieses
                // Häkchen setzt, hat den Mailversand der Kundeninstanzen
                // wirklich in Betrieb genommen.
                'active' => false,
                // Ein Relay ohne Anmeldung ist erlaubt (siehe Mailbox::
                // isConfigured()) — aber es ist die Ausnahme, und ein
                // vorbelegtes „braucht kein Passwort" läse sich wie eine
                // Aussage über einen Server, den hier noch niemand kennt.
                'authenticates' => true,
            ])->save();
        });
    }

    public function down(): void
    {
        DB::table('mailboxes')->where('key', self::KEY)->delete();
    }
};
