<?php

declare(strict_types=1);

namespace App\Middlewares;

use App\Helpers\Request;
use App\Helpers\Response;

class RateLimitMiddleware
{
    private int $maxAttempts;
    private int $windowSeconds;

    public function __construct(int $maxAttempts = 5, int $windowSeconds = 300)
    {
        $this->maxAttempts = $maxAttempts;
        $this->windowSeconds = $windowSeconds;
    }

    public function handle(Request $request): mixed
    {
        $ip = $request->getClientIp();
        $endpoint = $request->uri();
        $key = md5($ip . $endpoint);

        $rateFile = STORAGE_PATH . '/rate_limits/' . $key . '.json';
        $this->ensureDir(dirname($rateFile));

        $fp = fopen($rateFile, 'c+');
        if (!$fp) {
            return null;
        }

        flock($fp, LOCK_EX);

        $filesize = filesize($rateFile);
        $attempts = $filesize > 0 ? (json_decode(fread($fp, $filesize), true) ?: []) : [];

        $now = time();
        $attempts = array_filter($attempts, fn($t) => $t > ($now - $this->windowSeconds));
        $attempts[] = $now;

        ftruncate($fp, 0);
        rewind($fp);
        fwrite($fp, json_encode(array_values($attempts)));
        flock($fp, LOCK_UN);
        fclose($fp);

        if (count($attempts) > $this->maxAttempts) {
            return 'Demasiadas solicitudes. Intente de nuevo más tarde.';
        }

        return null;
    }

    private function ensureDir(string $path): void
    {
        if (!is_dir($path)) {
            mkdir($path, 0755, true);
        }
    }
}
