<?php

use App\Livewire\Admin\Integrations;
use App\Models\Operator;
use App\Services\Secrets\SecretVault;
use App\Support\OperatingMode;
use App\Support\Readiness\BillingChecks;
use App\Support\StripeWebhookSecret;
use Livewire\Livewire;

/**
 * Ein Stripe-Wert in der Konsole und zwei in der Serverdatei ist keine
 * Entscheidung, sondern ein Zustand. Die alte Begründung — „wird bei jedem
 * eingehenden Zahlungsereignis gelesen, ein Datenbankproblem ließe die
 * Signaturprüfung still fehlschlagen" — hält nicht: der Secret Key, mit dem
 * das Geld eingezogen wird, liegt längst im Tresor und wird bei jeder Buchung
 * gelesen. Und die AUSWAHL zwischen Test- und Live-Signaturschlüssel fragte
 * ohnehin schon die Datenbank (OperatingMode::current()).
 *
 * Beide Werte sind jetzt ein Tresoreintrag mit den zwei Plätzen, die der
 * Tresor für Test und Live sowieso führt.
 */
beforeEach(function () {
    config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
});

it('prefers the stored signing secret over the server file', function () {
    config()->set('services.stripe.webhook_secret_test', 'whsec_from_env');
    OperatingMode::set(OperatingMode::Test);

    app(SecretVault::class)->put('stripe.webhook_secret', 'whsec_from_console', Operator::factory()->create());

    expect(StripeWebhookSecret::current())->toBe('whsec_from_console');
});

it('keeps the two modes apart, stored just as in the server file', function () {
    // Der Grund, warum es überhaupt zwei Werte gibt: Stripe stellt je
    // Betriebsmodus ein eigenes Signaturgeheimnis aus. Ein Platz, der auf den
    // anderen zurückfällt, würde ein Testereignis mit dem Live-Schlüssel
    // prüfen — es scheitert, aber die Konsole sagt „gesetzt".
    $by = Operator::factory()->create();
    $vault = app(SecretVault::class);

    $vault->put('stripe.webhook_secret', 'whsec_test_slot', $by, OperatingMode::Test);
    $vault->put('stripe.webhook_secret', 'whsec_live_slot', $by, OperatingMode::Live);

    OperatingMode::set(OperatingMode::Test);
    expect(StripeWebhookSecret::current())->toBe('whsec_test_slot');

    OperatingMode::set(OperatingMode::Live);
    expect(StripeWebhookSecret::current())->toBe('whsec_live_slot');
});

it('still reads the server file when nothing is stored, per mode', function () {
    // Eine bestehende Installation hat beide Zeilen in der .env und darf sich
    // durch diesen Umzug nicht ändern — sonst weist sie ab morgen jedes
    // eingehende Zahlungsereignis ab.
    config()->set('services.stripe.webhook_secret', 'whsec_live_env');
    config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');

    OperatingMode::set(OperatingMode::Test);
    expect(StripeWebhookSecret::current())->toBe('whsec_test_env');

    OperatingMode::set(OperatingMode::Live);
    expect(StripeWebhookSecret::current())->toBe('whsec_live_env');
});

it('does not call an unset slot "from the server file" when the server file is empty for that mode', function () {
    // Die Herkunftsplakette auf der Karte muss zum Wert gehören, der WIRKLICH
    // gilt — genau der Fehler, den source() für dns.token schon einmal hatte.
    config()->set('services.stripe.webhook_secret', 'whsec_live_env');
    config()->set('services.stripe.webhook_secret_test', '');
    OperatingMode::set(OperatingMode::Test);

    expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('none')
        ->and(StripeWebhookSecret::current())->toBe('');
});

it('reports the source as the server file when that mode does have a line', function () {
    config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');
    OperatingMode::set(OperatingMode::Test);

    expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('environment');
});

it('offers the signing secret as a field on the payments card', function () {
    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'password')
        ->call('confirmPassword')
        ->assertSee('STRIPE_WEBHOOK_SECRET');
});

it('sends the readiness check to that card instead of the raw .env editor', function () {
    foreach (BillingChecks::all() as $check) {
        if ($check->key === 'billing.stripe_webhook_secret') {
            expect($check->tab)->toBe('services');

            return;
        }
    }

    throw new RuntimeException('billing.stripe_webhook_secret check is gone');
});
