<?php

declare(strict_types=1);

use Builder\Core\Tests\BuilderTestUser;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Schema;

beforeEach(function (): void {
    Schema::create('users', function ($table): void {
        $table->id();
        $table->string('name')->nullable();
        $table->string('email')->nullable()->unique();
        $table->string('password')->nullable();
        $table->timestamps();
    });

    config(['auth.providers.users.model' => BuilderTestUser::class]);

    // Override the testing-env shortcut in AuthServiceProvider so the
    // throttle:builder-login middleware sees a small, production-shaped limit.
    RateLimiter::for('builder-login', fn () => Limit::perMinute(2)->by('throttle-test-ip'));
});

it('blocks login attempts beyond the configured per-minute limit', function (): void {
    BuilderTestUser::create([
        'name' => 'Jane',
        'email' => 'jane@example.com',
        'password' => bcrypt('secret'),
    ]);

    $payload = ['email' => 'jane@example.com', 'password' => 'wrong'];

    // First two requests count against the limit and return validation errors.
    $this->post(route('builder.login.store'), $payload)->assertRedirect();
    $this->post(route('builder.login.store'), $payload)->assertRedirect();

    // Third request must hit the throttle middleware and produce 429.
    $this->post(route('builder.login.store'), $payload)->assertStatus(429);
});

it('blocks MFA challenge submissions beyond the configured per-minute limit', function (): void {
    $user = BuilderTestUser::create([
        'name' => 'Jane',
        'email' => 'jane@example.com',
        'password' => bcrypt('secret'),
    ]);

    $payload = ['code' => '000000'];

    $this->actingAs($user)->post(route('builder.mfa.challenge.store'), $payload);
    $this->actingAs($user)->post(route('builder.mfa.challenge.store'), $payload);

    $this->actingAs($user)
        ->post(route('builder.mfa.challenge.store'), $payload)
        ->assertStatus(429);
});
