<?php

declare(strict_types=1);

use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\RateLimiter;

beforeEach(function () {
    // Pest.php disables ThrottleRequests globally — re-enable for these tests.
    $this->withMiddleware(ThrottleRequests::class);
    RateLimiter::clear('login');
});

test('API login throttle eventually blocks after enough failed attempts', function () {
    // The login endpoint stacks two protections: middleware throttle:10,1 and a
    // controller-level RateLimiter keyed by IP+email (configurable via
    // security_auth.login_max_attempts, default 5). After enough hits, one of
    // them must kick in and return 429.
    $sawBlock = false;
    for ($i = 0; $i < 15; $i++) {
        $r = $this->postJson('/api/v1/login', ['email' => 'x@x.com', 'password' => 'wrong']);
        if ($r->getStatusCode() === 429) {
            $sawBlock = true;
            break;
        }
    }
    expect($sawBlock)->toBeTrue();
});

test('API forgot-password throttle blocks after 5 requests', function () {
    for ($i = 0; $i < 5; $i++) {
        $this->postJson('/api/v1/forgot-password', ['email' => 'x@x.com']);
    }

    $this->postJson('/api/v1/forgot-password', ['email' => 'x@x.com'])
        ->assertStatus(429);
});

test('API OTP send throttle blocks after 5 requests', function () {
    for ($i = 0; $i < 5; $i++) {
        $this->postJson('/api/v1/otp/send', ['email' => 'x@x.com']);
    }

    $this->postJson('/api/v1/otp/send', ['email' => 'x@x.com'])
        ->assertStatus(429);
});

test('API register throttle blocks after 5 requests', function () {
    for ($i = 0; $i < 5; $i++) {
        $this->postJson('/api/v1/register', []);
    }

    $this->postJson('/api/v1/register', [])->assertStatus(429);
});

test('2FA verify throttle blocks after 5 requests', function () {
    for ($i = 0; $i < 5; $i++) {
        $this->post('/2fa', ['code' => '123456']);
    }

    $this->post('/2fa', ['code' => '123456'])->assertStatus(429);
});

test('different IPs do not share the same rate-limit bucket', function () {
    for ($i = 0; $i < 5; $i++) {
        $this->call('POST', '/api/v1/forgot-password',
            parameters: ['email' => 'x@x.com'],
            server: ['REMOTE_ADDR' => '10.0.0.1']
        );
    }

    // Same email, different IP — should be fine
    $r = $this->call('POST', '/api/v1/forgot-password',
        parameters: ['email' => 'x@x.com'],
        server: ['REMOTE_ADDR' => '10.0.0.2']
    );
    expect($r->getStatusCode())->not->toBe(429);
});
