<?php

use App\Livewire\Admin\ConfirmSwitchMode;
use App\Livewire\Admin\Integrations;
use App\Models\Operator;
use App\Support\OperatingMode;
use Livewire\Livewire;

// Die Rollen heißen exakt so (Operator::OPERATOR_ROLES), und die Fabrik setzt
// sie über ->role(), nicht über eine ->owner()-Abkürzung. Das Testpasswort ist
// `passwort-fuer-tests` — OperatorFactory::definition().
//
// ZWEI PLAN-FEHLER (Brief/Plan wörtlich übernommen, hier korrigiert):
//
// 1. Livewire::actingAs() ohne den zweiten Parameter meldet nur den
//    'web'-Guard an — genau die Falle, die tests/Pest.php oben bereits für
//    operator()/admin() dokumentiert (§"Shared account helpers").
//    confirmationGuard() dieser Seite ist 'operator'.
// 2. ConfirmsPassword::confirmPassword() nimmt KEIN Argument entgegen — sie
//    liest die eigene Eigenschaft $confirmablePassword (so gesetzt in jedem
//    bestehenden Aufrufer, siehe tests/Feature/Admin/IntegrationsPageTest.php:
//    ->set('confirmablePassword', …)->call('confirmPassword')). Ein Aufruf
//    als ->call('confirmPassword', 'passwort-fuer-tests') kompiliert (PHP
//    verwirft überzählige Argumente stillschweigend), setzt die Eigenschaft
//    aber nie — die Prüfung vergleicht gegen einen leeren String und scheitert.
//
// Beide Fehler zusammen ließen den zweiten Test bei OperatingMode::Live
// stehen, obwohl scheinbar alles aufgerufen wurde: confirmPassword()
// scheiterte am Passwortvergleich, switchMode() brach danach in
// guardSecrets() mit 403 ab, bevor es je etwas schrieb.
it('refuses to switch without the secrets capability', function () {
    $admin = Operator::factory()->role('Admin')->create(); // hosts.manage, nicht secrets.manage

    Livewire::actingAs($admin, 'operator')
        ->test(Integrations::class)
        ->call('switchMode', 'test')
        ->assertForbidden();

    expect(OperatingMode::current())->toBe(OperatingMode::Live);
});

it('switches when the owner has confirmed their password', function () {
    $owner = Operator::factory()->role('Owner')->create();

    Livewire::actingAs($owner, 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'passwort-fuer-tests')
        ->call('confirmPassword')
        ->call('switchMode', 'test');

    expect(OperatingMode::current())->toBe(OperatingMode::Test);
});

it('refuses an unknown mode', function () {
    // Ein String aus dem Browser. `staging` gibt es nicht, und from() würde
    // hier eine Ausnahme werfen statt still nichts zu tun.
    $owner = Operator::factory()->role('Owner')->create();

    Livewire::actingAs($owner, 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'passwort-fuer-tests')
        ->call('confirmPassword')
        ->call('switchMode', 'staging');

    expect(OperatingMode::current())->toBe(OperatingMode::Live);
});

// ---- ConfirmSwitchMode selbst — nach dem Vorbild der ConfirmSaveSecret/
// ConfirmForgetSecret-Tests in tests/Feature/Admin/IntegrationsPageTest.php.
// Ein Modal ist OHNE die Route-Middleware der Seite erreichbar (R23-
// Kopfkommentar in CLAUDE.md) — "gelesen und für korrekt befunden" ist keine
// Prüfung, ein eigener Test schon.
it('does not open the switch confirmation without the capability', function () {
    $admin = Operator::factory()->role('Admin')->create(); // hosts.manage, nicht secrets.manage

    Livewire::actingAs($admin, 'operator')
        ->test(ConfirmSwitchMode::class, ['mode' => 'test'])
        ->assertForbidden();
});

it('confirms a switch through the modal without changing the mode itself', function () {
    $owner = Operator::factory()->role('Owner')->create();

    Livewire::actingAs($owner, 'operator')
        ->test(ConfirmSwitchMode::class, ['mode' => 'test'])
        ->call('confirm')
        ->assertDispatched('mode-switch-confirmed', mode: 'test');

    // Das Modal selbst ruft OperatingMode::set() nirgends auf — nur
    // Integrations::switchMode() darf das, hinter guardSecrets(). Bestätigen
    // im Modal allein darf den Modus nicht bewegen.
    expect(OperatingMode::current())->toBe(OperatingMode::Live);
});

// ---- Fix-Runde, Befund 1 (Important): keine Karte sagte, in welchen Platz
// sie schreibt. save()/render() lösen ohne Modus-Argument gegen
// OperatingMode::current() auf — funktional kein Problem, aber die Karte sah
// in Test und Live identisch aus. Reine Darstellung (secret-field.blade.php
// liest nur $mode, das Integrations::render() schon berechnet — kein neuer
// Aufruf von source()/outline()/updatedAt()), deshalb genügt ein assertSee je
// Modus statt eines erfundenen Verhaltens-Tests.
it('names the slot a saved value would land in, on the card itself', function () {
    $owner = Operator::factory()->role('Owner')->create();

    Livewire::actingAs($owner, 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'passwort-fuer-tests')
        ->call('confirmPassword')
        ->assertSee(__('secrets.slot.live'))
        ->assertDontSee(__('secrets.slot.test'));

    OperatingMode::set(OperatingMode::Test);

    Livewire::actingAs($owner, 'operator')
        ->test(Integrations::class)
        ->set('confirmablePassword', 'passwort-fuer-tests')
        ->call('confirmPassword')
        ->assertSee(__('secrets.slot.test'))
        ->assertDontSee(__('secrets.slot.live'));
});
