<?php

namespace Tests\Feature;

use App\Livewire\Settings\WebauthnKeys;
use App\Models\User;
use App\Models\WebauthnCredential;
use App\Services\WebauthnService;
use App\Support\Confirm\ConfirmToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

class WebauthnKeysTest extends TestCase
{
    use RefreshDatabase;

    public function test_register_stores_credential(): void
    {
        $user = User::factory()->create(['two_factor_secret' => 'x', 'two_factor_confirmed_at' => now()]);
        $this->actingAs($user);
        $svc = $this->mock(WebauthnService::class);
        $svc->shouldReceive('available')->andReturn(true);
        $svc->shouldReceive('verifyRegistration')->andReturnUsing(fn ($u, $r, $name) => WebauthnCredential::create([
            'user_id' => $u->id, 'name' => $name, 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0,
        ]));

        Livewire::test(WebauthnKeys::class)
            ->set('newName', 'YubiKey 5C')
            ->call('register', ['fake' => 'attestation'])
            ->assertHasNoErrors();

        $this->assertDatabaseHas('webauthn_credentials', ['user_id' => $user->id, 'name' => 'YubiKey 5C']);
    }

    public function test_options_validate_label_before_ceremony(): void
    {
        $user = User::factory()->create(['two_factor_secret' => 'x', 'two_factor_confirmed_at' => now()]);
        $this->actingAs($user);
        $this->mock(WebauthnService::class)->shouldReceive('available')->andReturn(true);

        Livewire::test(WebauthnKeys::class)
            ->set('newName', '')
            ->call('options')
            ->assertHasErrors('newName');
    }

    public function test_remove_deletes_credential(): void
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $cred = WebauthnCredential::create(['user_id' => $user->id, 'name' => 'k', 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0]);
        $this->mock(WebauthnService::class)->shouldReceive('available')->andReturn(true);

        $token = ConfirmToken::issue('webauthnKeyRemoved', ['id' => $cred->id]);
        ConfirmToken::confirm($token);
        Livewire::test(WebauthnKeys::class)->call('remove', $token);

        $this->assertDatabaseMissing('webauthn_credentials', ['id' => $cred->id]);
    }
}
