<?php

use App\Support\Navigation;
use App\Support\OpenWork;
use Illuminate\Support\Facades\File;

/**
 * Die Seite mit den offenen Punkten.
 *
 * Sie existiert, weil „was ist noch nicht fertig" bis dahin in Köpfen und
 * Notizen stand. Was diese Tests festhalten, ist nicht die Liste selbst — die
 * soll sich ändern, das ist ihr Zweck —, sondern dass jeder Eintrag
 * vollständig ist und die Seite nichts verschweigt.
 */
it('zeigt jeden offenen Punkt, ohne einen zu verschlucken', function () {
    $this->actingAs(admin(), 'operator')
        ->get(route('admin.open-work'))
        ->assertOk()
        ->assertSee(__('open_work.title'));

    $html = $this->actingAs(admin(), 'operator')->get(route('admin.open-work'))->getContent();

    foreach (OpenWork::all() as $item) {
        expect($html)->toContain(e($item['title']));
    }
});

it('nennt zu jedem Punkt wo, was fehlt und was passiert, wenn es so bleibt', function () {
    // Ohne den dritten Satz ist so eine Liste ein Wunschzettel: er entscheidet
    // die Reihenfolge, nicht das Gefühl.
    foreach (OpenWork::all() as $item) {
        foreach (['title', 'state', 'where', 'missing', 'risk'] as $field) {
            expect($item[$field] ?? '')->not->toBe('', "„{$item['title']}\" hat kein Feld {$field}.");
        }

        // Ein Zustand ohne Übersetzung wäre ein Kasten mit „open_work.state.x".
        expect(__('open_work.state.'.$item['state']))->not->toBe('open_work.state.'.$item['state']);
    }
});

it('führt die zwei bezahlten Module, die nichts tun, als solche', function () {
    // Der Anlass für die ganze Seite. Verschwinden sie hier stillschweigend,
    // ist die Liste wertlos — sie kosten Geld, solange sie offen sind.
    $sold = collect(OpenWork::all())->where('state', OpenWork::SOLD)->pluck('title')->implode(' ');

    expect($sold)->toContain('Sicherungsort')
        ->and($sold)->toContain('Office');
});

it('steht jedem offen, der die Konsole öffnen darf', function () {
    // Kein eigenes Recht: wer hier arbeitet, soll wissen, worauf er sich
    // verlassen kann und worauf nicht.
    $entry = collect(Navigation::console())
        ->flatMap(fn (array $g) => $g['items'])
        ->firstWhere(0, 'admin.open-work');

    expect($entry)->not->toBeNull()
        ->and($entry[3])->toBeNull();
});

it('stellt das nach vorne, was gerade Schaden anrichtet', function () {
    // Nicht in der Reihenfolge, in der es geschrieben wurde — sondern danach,
    // was ein Punkt HEUTE anrichtet. „Verkauft, nicht geliefert" kostet in
    // diesem Moment Geld; „beschlossen" tut gar nichts, bis jemand anfängt.
    expect(array_keys(OpenWork::grouped()))
        ->toBe(array_values(array_filter(
            OpenWork::ORDER,
            fn (string $s) => (OpenWork::counts()[$s] ?? 0) > 0,
        )));

    // Und der Sammelsatz oben nennt den dringendsten Zustand, der wirklich
    // vorkommt — nicht einen festen.
    expect(OpenWork::worst())->toBe(array_key_first(OpenWork::grouped()));
});

it('lässt keine leere Gruppe stehen', function () {
    // Eine Überschrift ohne Inhalt liest sich wie ein Ladefehler. Derselbe
    // Fehler, der in der Seitenleiste schon einmal zuschlug.
    foreach (OpenWork::grouped() as $state => $items) {
        expect($items)->not->toBeEmpty("Gruppe {$state} ist leer.");
    }
});

it('folgt der Formensprache der Bereitschaftsseite, nicht der eines Formulars', function () {
    // Die erste Fassung nahm das Muster der Anlegen-Seite: `lbl`-Etikett,
    // große Kopfzeile, pro Punkt eine eigene Karte. Für eine Liste mit
    // Zuständen gibt es in dieser Konsole längst ein Muster, und zwei Muster
    // für ein Problem sind zwei Sprachen.
    $page = File::get(resource_path('views/livewire/admin/open-work.blade.php'));

    expect($page)->toContain('divide-y divide-line')
        // Und keine Zustands-Plakette je Zeile: die Karte darüber sagt den
        // Zustand, alle Zeilen darin teilen ihn. Sie wiederholte dasselbe Wort
        // dreimal pro Bildschirm.
        ->and($page)->not->toContain('<x-ui.badge')
        // Kein Etikett und keine Formular-Kopfzeile.
        ->and($page)->not->toContain('lbl">')
        ->and($page)->not->toContain('min-[901px]:text-[30px]');
});

it('nutzt die Breite, die das Layout hergibt, statt in der Mitte aufzuhören', function () {
    // Gegen das AUSGELIEFERTE HTML geprüft, nicht gegen die Blade-Quelle: dort
    // steht der Klassenname auch im Kommentar, der erklärt, warum er weg ist —
    // und ein Test, der einen Kommentar liest, prüft nicht, was ankommt.
    $html = $this->actingAs(admin(), 'operator')->get(route('admin.open-work'))->getContent();

    // Das Layout erlaubt 1320 px. Eine feste Zeichenbreite ließ rechts die
    // halbe Karte leer; die volle Breite ohne Grenze ergäbe rund 165 Zeichen
    // je Zeile. Zwei Spalten sind die Antwort auf beides.
    expect($html)->not->toContain('max-w-[76ch]')
        ->and($html)->toContain('lg:grid-cols-2');
});
