<?php

declare(strict_types=1);

namespace Tests\Unit\Middlewares;

use App\Helpers\Request;
use App\Middlewares\RateLimitMiddleware;
use Tests\TestCase;

class RateLimitMiddlewareTest extends TestCase
{
    protected function tearDown(): void
    {
        $files = glob(STORAGE_PATH . '/rate_limits/*.json');
        foreach ($files as $file) {
            if (basename($file) !== '.gitkeep') {
                @unlink($file);
            }
        }
        parent::tearDown();
    }

    public function testFirstRequestPasses(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REQUEST_URI'] = '/api/auth/login';
        $_SERVER['REMOTE_ADDR'] = '192.168.1.1';

        $middleware = new RateLimitMiddleware(5, 300);
        $request = new Request();
        $result = $middleware->handle($request);

        $this->assertNull($result);
    }

    public function testUnderLimitPasses(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REQUEST_URI'] = '/api/auth/login';
        $_SERVER['REMOTE_ADDR'] = '10.0.0.1';

        $middleware = new RateLimitMiddleware(5, 300);
        $request = new Request();

        for ($i = 0; $i < 5; $i++) {
            $refresh = new Request();
            $result = $middleware->handle($refresh);
            $this->assertNull($result, "Request {$i} should pass");
        }
    }

    public function testOverLimitFails(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REQUEST_URI'] = '/api/auth/login';
        $_SERVER['REMOTE_ADDR'] = '10.0.0.2';

        $middleware = new RateLimitMiddleware(2, 300);
        $request = new Request();

        $this->assertNull($middleware->handle($request));

        $request2 = new Request();
        $this->assertNull($middleware->handle($request2));

        $request3 = new Request();
        $result = $middleware->handle($request3);
        $this->assertIsString($result);
        $this->assertStringContainsString('Demasiadas', $result);
    }

    public function testDifferentEndpointsIndependent(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REMOTE_ADDR'] = '10.0.0.3';

        $middleware = new RateLimitMiddleware(1, 300);

        $_SERVER['REQUEST_URI'] = '/api/auth/login';
        $this->assertNull($middleware->handle(new Request()));
        $this->assertIsString($middleware->handle(new Request()));

        $_SERVER['REQUEST_URI'] = '/api/auth/forgot-password';
        $this->assertNull($middleware->handle(new Request()));
    }

    public function testCustomLimits(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $_SERVER['REQUEST_URI'] = '/api/custom';
        $_SERVER['REMOTE_ADDR'] = '10.0.0.4';

        $middleware = new RateLimitMiddleware(3, 300);
        $request = new Request();

        for ($i = 0; $i < 3; $i++) {
            $this->assertNull($middleware->handle(new Request()));
        }

        $this->assertIsString($middleware->handle(new Request()));
    }
}
