<?php

use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
 * Ein Sitz fuehrt ab hier ZWEI Angaben nebeneinander.
 *
 * `status` ist, was der Inhaber WILL — er aendert sich sofort beim Klick.
 * `nc_state` ist, was in der Nextcloud WIRKLICH ist — er aendert sich, wenn
 * der Auftrag durch ist. Ein einzelnes Feld muesste luegen: entweder es
 * behauptet einen Erfolg, den nur die Warteschlange bringen kann, oder es
 * verschweigt dem Inhaber, dass sein Klick angekommen ist.
 *
 * Nur so laesst sich "fehlgeschlagen" ueberhaupt sagen.
 *
 * ## Warum das Nachziehen unten den Query Builder benutzt, nicht Seat::linkToInstanceAdmin()
 *
 * Eine Wanderung soll einfrieren, was zum Zeitpunkt ihres Schreibens galt.
 * Riefe up() stattdessen die Modellmethode auf, wuerde jeder kuenftige Lauf
 * gegen eine frische Datenbank — CI, ein neuer Entwickler, `migrate:fresh` —
 * die DANN aktuelle Fassung dieser Methode ausfuehren, nicht die von heute.
 * Heute ist sie harmlos; bekommt sie spaeter eine Nebenwirkung (einen
 * API-Aufruf, einen Warteschlangen-Auftrag), faehrt jede Wanderung, die je
 * ueber diese Zeile lief, sie rueckwirkend mit — ohne dass es jemand so
 * wollte. Der Block unten ist deshalb eine eigene, bewusst duplizierte
 * Fassung derselben Auswahl (Instanz mit status in active/
 * cancellation_scheduled, juengste zuerst, nur bei gesetztem nc_admin_ref).
 * BITTE NICHT „aufraeumen" und durch den Modellaufruf ersetzen — das ist
 * genau die Kopplung, die hier vermieden wird.
 *
 * `nc_admin_ref` ist am Instance-Modell 'encrypted' gecastet; roher
 * DB::table()-Zugriff liefert den Chiffretext. Crypt::decryptString() ist
 * exakt dieselbe Entschluesselung, die der Cast im Hintergrund aufruft —
 * ohne dafuer eine Modellklasse zu laden.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('seats', function (Blueprint $table) {
            // Einmal gesetzt, nie wieder geaendert: Nextcloud kann Benutzer
            // nicht umbenennen.
            $table->string('nc_username')->nullable()->after('email');
            $table->string('nc_state', 16)->default('none')->after('status');
            $table->text('nc_error')->nullable()->after('nc_state');
            $table->timestamp('nc_synced_at')->nullable()->after('nc_error');
        });

        // Bestandssitze sind ehrlich beschrieben: angelegt, nie eingeladen —
        // denn eingeladen hat sie nie jemand, resend() war eine Attrappe.
        // EINE Ausnahme: der Inhaber-Sitz IST das Admin-Konto der Instanz.
        DB::table('seats')->where('role', 'owner')->chunkById(100, function ($sitze) {
            foreach ($sitze as $sitz) {
                $roh = DB::table('instances')
                    ->where('customer_id', $sitz->customer_id)
                    ->whereIn('status', ['active', 'cancellation_scheduled'])
                    ->orderByDesc('id')
                    ->value('nc_admin_ref');

                if ($roh === null) {
                    continue;
                }

                try {
                    $ref = Crypt::decryptString($roh);
                } catch (DecryptException) {
                    // Nicht entschluesselbar (z. B. ein Schluesselwechsel ohne
                    // Migration der Altwerte) wird wie „kein Konto" behandelt —
                    // ein Wanderungslauf darf daran nicht scheitern.
                    continue;
                }

                if (blank($ref)) {
                    continue;
                }

                DB::table('seats')->where('id', $sitz->id)->update([
                    'nc_username' => $ref,
                    'nc_state' => 'synced',
                    'nc_synced_at' => now(),
                ]);
            }
        });
    }

    public function down(): void
    {
        Schema::table('seats', function (Blueprint $table) {
            $table->dropColumn(['nc_username', 'nc_state', 'nc_error', 'nc_synced_at']);
        });
    }
};
