<?php

namespace Tests\Feature\Auth;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class TurnstileVerificationTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        Config::set('services.turnstile.secret_key', 'test-secret-key');
        Config::set('services.turnstile.site_key', 'test-site-key');
    }

    /**
     * @return array<string, mixed>
     */
    private function registrationPayload(array $extras = []): array
    {
        return [
            'first_name' => 'Test',
            'last_name' => 'User',
            'email' => 'turnstile-user@example.com',
            'contact_number' => '+1 555 123 4567',
            'country' => 'US',
            'password' => 'password',
            'password_confirmation' => 'password',
            ...$extras,
        ];
    }

    public function test_login_requires_turnstile_response_when_secret_configured(): void
    {
        $user = User::factory()->create();

        Http::fake();

        $this->from(route('login'))
            ->post(route('login.store'), [
                'email' => $user->email,
                'password' => 'password',
            ])
            ->assertSessionHasErrors('cf-turnstile-response');

        Http::assertNothingSent();
    }

    public function test_login_rejects_turnstile_failure_from_cloudflare(): void
    {
        Http::fake([
            'challenges.cloudflare.com/*' => Http::response([
                'success' => false,
                'error-codes' => ['invalid-input-response'],
            ]),
        ]);

        $user = User::factory()->create();

        $this->from(route('login'))
            ->post(route('login.store'), [
                'email' => $user->email,
                'password' => 'password',
                'cf-turnstile-response' => 'bad-token',
            ])
            ->assertSessionHasErrors('cf-turnstile-response');

        Http::assertSent(fn ($request) => str_contains(
            (string) $request->url(),
            'challenges.cloudflare.com/turnstile/v0/siteverify',
        ));

        $this->assertGuest();
    }

    public function test_login_authenticates_when_cloudflare_turnstile_succeeds(): void
    {
        Http::fake([
            'challenges.cloudflare.com/*' => Http::response(['success' => true]),
        ]);

        $user = User::factory()->create();

        $this->post(route('login.store'), [
            'email' => $user->email,
            'password' => 'password',
            'cf-turnstile-response' => 'accepted-token',
        ])->assertRedirect(route('dashboard', absolute: false));

        $this->assertAuthenticated();
        Http::assertSent(fn ($request) => str_contains(
            (string) $request->url(),
            'challenges.cloudflare.com/turnstile/v0/siteverify',
        ));
    }

    public function test_registration_requires_turnstile_when_secret_configured(): void
    {
        Http::fake();

        $this->from(route('register'))
            ->post(route('register.store'), $this->registrationPayload())
            ->assertSessionHasErrors('cf-turnstile-response');

        Http::assertNothingSent();
    }

    public function test_registration_completes_when_cloudflare_turnstile_succeeds(): void
    {
        Http::fake([
            'challenges.cloudflare.com/*' => Http::response(['success' => true]),
        ]);

        $this->post(route('register.store'), $this->registrationPayload([
            'cf-turnstile-response' => 'accepted-token',
        ]))->assertRedirect(route('dashboard', absolute: false));

        Http::assertSent(fn ($request) => str_contains(
            (string) $request->url(),
            'challenges.cloudflare.com/turnstile/v0/siteverify',
        ));

        $this->assertAuthenticated();
        $this->assertNotNull(User::query()->where('email', 'turnstile-user@example.com')->first());
    }
}
