<?php

namespace App\Support;

/**
 * Test oder Live — welcher Satz Zugangsdaten gilt.
 *
 * In `Settings` und nicht in der `.env`, weil `Settings` seinen Zwischenspeicher
 * beim Schreiben verwirft: ein Umlegen wirkt sofort, auch in den
 * Warteschlangen-Prozessen, die seit Stunden laufen. Eine `.env`-Variable
 * bräuchte einen Containerneustart — genau die Falle, die am 2026-07-30 eine
 * korrigierte DNS-Zone acht Stunden lang wirkungslos gelassen hat.
 *
 * Live ist die Vorgabe. Eine Installation, die nichts gespeichert hat, soll
 * nicht in einem Modus stehen, der stillschweigend andere Zugangsdaten benutzt.
 */
enum OperatingMode: string
{
    case Test = 'test';
    case Live = 'live';

    public const SETTING = 'platform.mode';

    public static function current(): self
    {
        // tryFrom, nicht from: ein unbekannter Wert in der Zeile ist ein
        // Datenfehler und darf nicht jede Anfrage in eine Ausnahme werfen.
        return self::tryFrom((string) Settings::get(self::SETTING, self::Live->value))
            ?? self::Live;
    }

    public static function set(self $mode): void
    {
        Settings::set(self::SETTING, $mode->value);
    }

    /**
     * Zu welchem Modus ein Stripe-Schlüssel gehört — am Präfix, ohne Netzverkehr.
     *
     * Stripe beschriftet den Schlüssel nicht; das Präfix ist das Einzige, was
     * bei beiden Schlüsselarten (`sk_`, und der eingeschränkte `rk_`) wahr ist.
     * Das reicht, und es muss reichen: die Bereitschaftsseite darf beim
     * Seitenaufruf nichts erreichen, und die Migration läuft, bevor irgendein
     * Dienst antwortet.
     *
     * `null` heißt „nicht entscheidbar", nicht „live". Wer daraus eine
     * Vorgabe braucht, sagt sie an seiner Stelle selbst — die Migration setzt
     * `?? Live` (der Zustand vor ihr, also Fortsetzung statt neuer Behauptung),
     * die Bereitschaftsprüfung meldet dagegen NUR einen Widerspruch, den sie
     * beweisen kann.
     *
     * Diese eine Stelle, weil dieselbe Frage vorher an drei Orten unabhängig
     * beantwortet wurde: in der Migration, in StripeCheck und — gar nicht — auf
     * der Bereitschaftsseite. Drei Formulierungen einer Frage sind der Weg, auf
     * dem sie auseinanderlaufen.
     */
    public static function ofStripeKey(?string $secret): ?self
    {
        $secret = trim((string) $secret);

        // `pk_` gehört mit dazu, seit der veröffentlichbare Schlüssel ein Feld
        // hat (App\Support\StripePublishableKey): ein pk_live im Testplatz ist
        // dieselbe Verwechslung wie ein sk_live dort, nur harmloser — und ohne
        // diese zwei Zeilen wäre das Feld ein reiner Ablageplatz, den niemand
        // je gegen etwas prüft.
        return match (true) {
            str_starts_with($secret, 'sk_test_'), str_starts_with($secret, 'rk_test_'),
            str_starts_with($secret, 'pk_test_') => self::Test,
            str_starts_with($secret, 'sk_live_'), str_starts_with($secret, 'rk_live_'),
            str_starts_with($secret, 'pk_live_') => self::Live,
            default => null,
        };
    }

    public function isTest(): bool
    {
        return $this === self::Test;
    }
}
