<?php

namespace Tests\Feature\Security;

use Illuminate\Support\Facades\Route;
use Tests\TestCase;

/**
 * Las rutas de recuperar contraseña tienen tope por IP.
 *
 * **No estaban abiertas del todo** y conviene tenerlo claro: el broker de contraseñas ya
 * limitaba el reenvío **por email** (`config/auth.php`, `throttle => 60`) y el login lleva
 * su propio límite de cinco intentos. Lo que faltaba era el tope **por IP**, que es lo que
 * impide recorrer muchas direcciones distintas: con el límite solo por email, probar mil
 * correos cuesta lo mismo que probar uno (MGR-014).
 *
 * Se comprueba sobre la definición de la ruta y no lanzando 7 peticiones: el límite lo
 * aplica el middleware de Laravel, que ya está probado; lo que puede desaparecer sin que
 * nadie se dé cuenta es **que la ruta lo lleve puesto**.
 */
class ThrottleDeAutenticacionTest extends TestCase
{
    /**
     * @return array<string, array{string}>
     */
    public static function rutasQueLoNecesitan(): array
    {
        return [
            'pedir el correo de recuperación' => ['password.request'],
            'la pantalla de poner la nueva' => ['password.reset'],
        ];
    }

    /**
     * @dataProvider rutasQueLoNecesitan
     */
    public function test_la_ruta_lleva_tope_por_ip(string $nombre): void
    {
        $ruta = Route::getRoutes()->getByName($nombre);

        $this->assertNotNull($ruta, "la ruta {$nombre} tiene que existir");

        // `gatherMiddleware()` devuelve los **alias sin resolver** —`throttle:6,1`—, no
        // la clase: `route:list` los resuelve para pintarlos, esto no. Se buscan las dos
        // formas por si algún día se pone la clase directamente.
        $topes = array_filter(
            $ruta->gatherMiddleware(),
            fn ($m) => is_string($m)
                && (str_starts_with($m, 'throttle') || str_contains($m, 'ThrottleRequests'))
        );

        $this->assertNotEmpty($topes,
            "{$nombre} sin `throttle`: se puede recorrer una lista de correos desde una sola IP");
    }

    public function test_el_verificador_de_email_sigue_teniendo_el_suyo(): void
    {
        // Era el único que lo tenía en `routes/auth.php`, y de ahí salió el número que se
        // ha usado para las otras dos: seis por minuto.
        $ruta = Route::getRoutes()->getByName('verification.verify');

        $this->assertNotNull($ruta);
        $this->assertTrue(
            collect($ruta->gatherMiddleware())->contains(
                fn ($m) => is_string($m) && (str_starts_with($m, 'throttle') || str_contains($m, 'Throttle'))
            ),
            'verification.verify tiene que conservar su tope'
        );
    }
}
