<?php

namespace App\Http\Controllers;

use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * Dateien, die jeder herunterladen darf: AGB, Auftragsverarbeitungsvertrag,
 * technische und organisatorische Maßnahmen, Preisblätter.
 *
 * Sie liegen in `storage/app/files/public/` und werden ausgeliefert, wie sie
 * sind. Kein Verwaltungsbereich, keine Datenbanktabelle: eine Datei ablegen
 * genügt, und was nicht dort liegt, gibt es nicht.
 *
 * ---------------------------------------------------------------------------
 * Warum eine eigene Adresse
 * ---------------------------------------------------------------------------
 *
 * Diese Dateien stehen in Verträgen und auf Rechnungen. Eine Adresse, die beim
 * nächsten Umbau des Portals wandert, macht aus jedem dieser Verweise einen
 * toten Link — und zwar rückwirkend, in Dokumenten, die längst verschickt sind.
 * Ein eigener Hostname ist die einzige Zusage, die sich einhalten lässt.
 *
 * ---------------------------------------------------------------------------
 * Versionierte Dateinamen
 * ---------------------------------------------------------------------------
 *
 * `agb-2026-01.pdf`, nicht `agb.pdf`. Eine Fassung, auf die ein Vertrag
 * verweist, darf sich unter derselben Adresse NIE ändern — sonst zeigt der
 * Verweis in einem Vertrag vom Januar plötzlich auf Bedingungen vom Juli, und
 * niemand kann mehr sagen, was vereinbart war. Neue Fassung heißt neue Datei.
 *
 * Erzwungen wird das hier nicht — eine Regel, die eine Datei mit dem falschen
 * Namen abweist, hilft niemandem, der eine hochladen will. Sie steht hier, weil
 * dies die Stelle ist, an der jemand nachsieht.
 */
class PublicFileController extends Controller
{
    private const ROOT = 'app/files/public';

    public function __invoke(string $file): BinaryFileResponse
    {
        // NUR der Dateiname, ohne Pfad. `basename()` macht aus
        // `../../.env` ein `.env`, und das liegt in diesem Verzeichnis nicht —
        // damit ist der Pfad-Ausbruch beantwortet, bevor er anfängt. Ein
        // Verzeichnisbaum unter `public/` gibt es absichtlich nicht: er wäre
        // die zweite Gelegenheit für denselben Fehler.
        $name = basename($file);

        // Ein Punktdatei-Name kommt hier nicht durch. Sie sind in diesem
        // Verzeichnis nicht vorgesehen, und ihr Vorkommen wäre ein Versehen.
        if ($name === '' || str_starts_with($name, '.')) {
            abort(404);
        }

        $path = storage_path(self::ROOT.'/'.$name);

        if (! is_file($path)) {
            abort(404);
        }

        // Inline, nicht als Anhang: eine AGB, die der Browser anzeigt, wird
        // gelesen; eine, die er herunterlädt, wird weggeklickt.
        return response()->file($path, [
            'Content-Disposition' => 'inline; filename="'.$name.'"',
        ]);
    }
}
