<?php

namespace Tests\Feature;

use App\Livewire\Auth\TwoFactorChallenge;
use App\Models\User;
use App\Models\WebauthnCredential;
use App\Services\WebauthnService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

class ChallengeFactorAdaptTest extends TestCase
{
    use RefreshDatabase;

    private function keyOnlyUser(): User
    {
        $u = User::factory()->create();
        WebauthnCredential::create(['user_id' => $u->id, 'name' => 'k', 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0]);

        return $u->fresh();
    }

    public function test_totp_user_sees_the_field(): void
    {
        $user = User::factory()->create(['two_factor_secret' => 'S', 'two_factor_confirmed_at' => now()]);
        session(['2fa.user' => $user->id, '2fa.remember' => false]);

        Livewire::test(TwoFactorChallenge::class)->assertSet('pendingHasTotp', true);
    }

    public function test_totp_user_sees_the_backup_link_but_not_the_backup_field(): void
    {
        $user = User::factory()->create(['two_factor_secret' => 'S', 'two_factor_confirmed_at' => now()]);
        session(['2fa.user' => $user->id, '2fa.remember' => false]);

        Livewire::test(TwoFactorChallenge::class)
            ->assertSee('000000')                                  // TOTP field present
            ->assertSee(__('auth.challenge_use_backup'))           // backup link present
            ->assertDontSee(__('auth.challenge_backup_placeholder')); // no backup field here
    }

    public function test_key_only_user_without_secure_context_is_redirected_to_the_backup_view(): void
    {
        // No domain configured → webauthnAvailable() false, pendingHasTotp false: the backup code
        // is the only usable path, so mount() sends the user straight to the dedicated view.
        $user = $this->keyOnlyUser();
        session(['2fa.user' => $user->id, '2fa.remember' => false]);

        Livewire::test(TwoFactorChallenge::class)
            ->assertRedirect(route('two-factor.challenge.backup'));
    }

    public function test_key_only_user_with_secure_context_stays_and_shows_key_plus_backup(): void
    {
        $svc = $this->mock(WebauthnService::class);
        $svc->shouldReceive('available')->andReturn(true);

        $user = $this->keyOnlyUser();
        session(['2fa.user' => $user->id, '2fa.remember' => false]);

        Livewire::test(TwoFactorChallenge::class)
            ->assertNoRedirect()
            ->assertSee(__('auth.webauthn_login'))                 // security-key button
            ->assertSee(__('auth.challenge_use_backup'))           // backup link
            ->assertDontSee('000000')                              // no TOTP field
            ->assertDontSee(__('auth.challenge_backup_placeholder')); // no inline backup field
    }

    public function test_totp_and_key_user_with_secure_context_sees_field_key_alt_and_backup(): void
    {
        $svc = $this->mock(WebauthnService::class);
        $svc->shouldReceive('available')->andReturn(true);

        $user = User::factory()->create(['two_factor_secret' => 'S', 'two_factor_confirmed_at' => now()]);
        WebauthnCredential::create(['user_id' => $user->id, 'name' => 'k', 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0]);
        session(['2fa.user' => $user->id, '2fa.remember' => false]);

        Livewire::test(TwoFactorChallenge::class)
            ->assertNoRedirect()
            ->assertSee('000000')                          // TOTP field
            ->assertSee(__('auth.webauthn_login'))         // secondary security-key button (nested branch)
            ->assertSee(__('auth.challenge_use_backup'));  // backup link
    }
}
