<?php

use App\Livewire\Admin\Integrations;
use App\Support\OperatingMode;
use App\Support\StripePublishableKey;
use Livewire\Livewire;

/**
 * Stripe gibt einem Betreiber DREI Werte zum Eintragen: veröffentlichbarer
 * Schlüssel, Secret Key, Signatur-Secret. Zwei davon hatten hier ein Feld.
 *
 * Der veröffentlichbare wird von dieser Installation heute nicht gelesen — die
 * Kasse leitet auf Stripes eigene Bezahlseite weiter, im Browser läuft kein
 * Stripe.js. Er gehört trotzdem hierher: wer ein Konto einrichtet, hat drei
 * Werte vor sich und muss nicht raten, welcher der beiden Felder welcher ist
 * und wo der dritte hinsoll.
 *
 * Deshalb aber KEIN Tresoreintrag: der Wert ist öffentlich, und ein Feld, das
 * ihn hinter „nie wieder vollständig angezeigt" versteckt, wäre Theater. Eine
 * gewöhnliche Einstellung, im Klartext sichtbar — mit demselben Platz je
 * Betriebsmodus wie die zwei Schlüssel daneben, denn Stripe stellt auch ihn je
 * Konto eigen aus.
 */
it('keeps a publishable key per operating mode', function () {
    // Beide Plätze ausdrücklich benannt: der Vorgabemodus dieser Installation
    // ist `live`, und ohne Argument landeten sonst beide Werte im selben Platz
    // — der Test bewiese dann genau nichts.
    StripePublishableKey::set('pk_test_abc', OperatingMode::Test);
    StripePublishableKey::set('pk_live_xyz', OperatingMode::Live);

    OperatingMode::set(OperatingMode::Live);

    expect(StripePublishableKey::current())->toBe('pk_live_xyz');

    OperatingMode::set(OperatingMode::Test);
    expect(StripePublishableKey::current())->toBe('pk_test_abc');
});

it('falls back to the server file, per mode', function () {
    config()->set('services.stripe.key', 'pk_live_from_env');
    config()->set('services.stripe.key_test', 'pk_test_from_env');

    OperatingMode::set(OperatingMode::Test);
    expect(StripePublishableKey::current())->toBe('pk_test_from_env');

    OperatingMode::set(OperatingMode::Live);
    expect(StripePublishableKey::current())->toBe('pk_live_from_env');
});

it('recognises which account a publishable key belongs to', function () {
    // Damit das Feld nicht bloß ein Ablageplatz ist: derselbe Präfix-Blick, den
    // der Secret Key längst bekommt. Ein pk_live im Testplatz ist genau die
    // Verwechslung, die beim Einrichten passiert.
    expect(OperatingMode::ofStripeKey('pk_test_abc'))->toBe(OperatingMode::Test)
        ->and(OperatingMode::ofStripeKey('pk_live_abc'))->toBe(OperatingMode::Live)
        ->and(OperatingMode::ofStripeKey('irgendwas'))->toBeNull();
});

it('saves it from the console and shows it in full', function () {
    config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
    OperatingMode::set(OperatingMode::Test);

    $page = Livewire::actingAs(operator('Owner'), 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'password')
        ->call('confirmPassword')
        ->set('stripePublishableKey', 'pk_test_visible123')
        ->call('savePublishableKey')
        ->assertHasNoErrors();

    expect(StripePublishableKey::current())->toBe('pk_test_visible123');

    // Im Klartext, anders als die zwei Geheimnisse daneben — er ist
    // öffentlich. Am Snapshot geprüft, nicht am HTML: `x-ui.input` rendert
    // serverseitig kein `value`, Livewire hydriert das Feld aus genau diesem
    // Snapshot. Ein Tresorwert steht dort NIE (siehe IntegrationsPageTest,
    // „never puts a stored secret into the component snapshot") — dieser
    // schon, und das ist der Unterschied, um den es hier geht.
    expect(json_encode($page->snapshot))->toContain('pk_test_visible123');
});

it('says when the pasted key belongs to the other account', function () {
    config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
    OperatingMode::set(OperatingMode::Test);
    StripePublishableKey::set('pk_live_wrong_slot');

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'password')
        ->call('confirmPassword')
        ->assertSee(__('secrets.publishable_wrong_mode', [
            'mode' => __('readiness.mode.live'),
        ]));
});
