<?php

use App\Models\PlanFamily;
use App\Models\User;
use App\Services\Billing\PlanCatalogue;
use App\Services\Stripe\FakeStripeClient;
use App\Services\Stripe\StripeClient;

/**
 * Ein Paket, das nur der Betrieb sieht.
 *
 * Das Testpaket ist für Abnahmeläufe da. Es aus dem Verkauf zu nehmen, indem
 * man `sales_enabled` abschaltet, nähme es auch aus dem Verschenken —
 * currentVersion() wirft dann bei einer nicht verkäuflichen Familie —, und
 * genau dafür existiert `internal` als eigenes Feld.
 *
 * Das Testpaket legte der Betreiber früher von Hand über die Konsole an; seit
 * der Umschaltung auf die neue Leiter bringt es die Migration mit, damit eine
 * frische Installation nicht erst ein Paket erfinden muss, um eine Abnahme zu
 * fahren. Diese Tests lesen deshalb, was dort steht, statt sich ein eigenes zu
 * bauen.
 */
beforeEach(function () {
    $this->stripe = new FakeStripeClient;
    app()->instance(StripeClient::class, $this->stripe);

    // Der Bestand, gegen den hier geprüft wird: die Familie ist da, sie ist
    // intern, und sie steht im Verkauf — denn `sales_enabled` schaltet auch das
    // Verschenken ab, und genau das soll `internal` nicht tun.
    $family = PlanFamily::query()->where('key', 'test')->sole();

    expect($family->internal)->toBeTrue()
        ->and($family->sales_enabled)->toBeTrue();
});

it('zeigt ein internes Paket nicht im Verkauf', function () {
    expect(array_keys(app(PlanCatalogue::class)->sellable()))->not->toContain('test');
});

it('lässt ein internes Paket weiterhin verschenken', function () {
    // currentVersion() ist der Weg, den GrantPlan benutzt — wirft er hier,
    // ist das Verschenken mit abgeschaltet, und genau das soll `internal`
    // gerade NICHT tun.
    expect(app(PlanCatalogue::class)->currentVersion('test')->quota_gb)->toBe(5);
});

it('lehnt einen Checkout auf ein internes Paket ab, nicht unterscheidbar von einem unbekannten', function () {
    $buyer = User::factory()->create(['email_verified_at' => now()]);

    // Eine URL ist keine Liste: dass "test" in keinem Preisblatt steht, hält
    // niemanden davon ab, den Schlüssel direkt zu posten. Erwartet wird
    // dieselbe Antwort wie für einen Schlüssel, den es gar nicht gibt — wer
    // die Preisliste nicht kennt, soll aus der Antwort nicht lernen können,
    // dass es dieses Paket gibt.
    $this->actingAs($buyer)
        ->post(route('checkout.start'), ['plan' => 'test', 'terms_accepted' => '1'])
        ->assertSessionHasErrors(['plan' => __('checkout.plan_gone')]);

    $this->actingAs($buyer)
        ->post(route('checkout.start'), ['plan' => 'gibt-es-nicht', 'terms_accepted' => '1'])
        ->assertSessionHasErrors(['plan' => __('checkout.plan_gone')]);

    expect($this->stripe->checkouts)->toBeEmpty();
});
