<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\WebauthnCredential;
use App\Services\DeploymentService;
use App\Services\WebauthnService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class WebauthnOptionsTest extends TestCase
{
    use RefreshDatabase;

    private function service(string $domain = 'panel.example.com'): WebauthnService
    {
        $d = $this->mock(DeploymentService::class);
        $d->shouldReceive('domain')->andReturn($domain);

        return app(WebauthnService::class);
    }

    public function test_registration_options_use_domain_rpid_and_store_challenge(): void
    {
        $user = User::factory()->create();
        $opts = $this->service()->registrationOptions($user);

        $this->assertSame('panel.example.com', data_get($opts, 'rp.id'));
        $this->assertNotEmpty(data_get($opts, 'challenge'));
        $this->assertNotNull(session('webauthn.register'));

        // Target a roaming hardware key (YubiKey) used as a one-touch second factor — not a
        // platform/password-manager passkey.
        $this->assertSame('cross-platform', data_get($opts, 'authenticatorSelection.authenticatorAttachment'));
        $this->assertSame('discouraged', data_get($opts, 'authenticatorSelection.residentKey'));
        $this->assertSame('discouraged', data_get($opts, 'authenticatorSelection.userVerification'));
        // WebAuthn L3 hint so passkey managers (Bitwarden) defer to the hardware key.
        $this->assertSame(['security-key'], data_get($opts, 'hints'));
    }

    public function test_assertion_options_require_only_user_presence(): void
    {
        $user = User::factory()->create();
        $opts = $this->service()->assertionOptions($user);

        // discouraged = a single touch on login, no PIN/biometric prompt.
        $this->assertSame('discouraged', data_get($opts, 'userVerification'));
        $this->assertSame(['security-key'], data_get($opts, 'hints'));
    }

    public function test_assertion_options_list_user_credentials(): void
    {
        $user = User::factory()->create();
        WebauthnCredential::create([
            'user_id' => $user->id, 'name' => 'k',
            'credential_id' => rtrim(strtr(base64_encode('rawid'), '+/', '-_'), '='),
            'public_key' => '{}', 'sign_count' => 0,
        ]);

        $opts = $this->service()->assertionOptions($user->fresh());

        $this->assertSame('panel.example.com', data_get($opts, 'rpId'));
        $this->assertNotEmpty(data_get($opts, 'allowCredentials'));
        $this->assertNotNull(session('webauthn.login'));
    }
}
