<?php
declare(strict_types=1);

namespace App\Middleware;

use App\Core\Middleware\MiddlewareInterface;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\ApiErrorCodes;

final class RateLimitMiddleware implements MiddlewareInterface
{
    private int $maxRequests = 60;
    private int $windowSeconds = 60;

    public function handle(Request $request, callable $next): Response
    {
        $ip = $request->ip();
        $routeKey = md5($ip . ':' . $request->method() . ':' . $request->path());

        $db = App::getInstance()->db();
        if (!$db) {
            return $next($request);
        }

        $now = date('Y-m-d H:i:s');
        $windowStart = date('Y-m-d H:i:s', time() - $this->windowSeconds);

        $row = $db->selectOne(
            "SELECT hits, window_start FROM api_rate_limits WHERE ip = ? AND route_key = ?",
            [$ip, $routeKey]
        );

        if (!$row || $row['window_start'] < $windowStart) {
            $db->query(
                "INSERT INTO api_rate_limits (ip, route_key, hits, window_start) VALUES (?, ?, 1, ?) "
                . "ON DUPLICATE KEY UPDATE hits = 1, window_start = ?",
                [$ip, $routeKey, $now, $now]
            );
            return $next($request);
        }

        if ((int) $row['hits'] >= $this->maxRequests) {
            $retryAfter = $this->windowSeconds - (time() - strtotime($row['window_start']));

            if ($request->isAjax() || $request->isJson() || $request->bearerToken()) {
                return (new Response())->json([
                    'success' => false,
                    'data' => null,
                    'meta' => null,
                    'errors' => [
                        'code' => ApiErrorCodes::RATE_LIMITED,
                        'message' => 'تم تجاوز الحد الأقصى للطلبات. حاول لاحقاً.',
                        'details' => ['retry_after' => max($retryAfter, 1)],
                    ],
                ], 429)->header('Retry-After', (string) max($retryAfter, 1));
            }

            return (new Response())->html(
                '<html dir="rtl" lang="ar"><head><meta charset="utf-8"><title>كثرة الطلبات</title>'
                . '<style>body{font-family:Cairo,sans-serif;text-align:center;padding:80px;}</style></head>'
                . '<body><h1>429</h1><p>تم تجاوز الحد الأقصى للطلبات. يرجى المحاولة لاحقاً.</p></body></html>',
                429
            );
        }

        $db->query(
            "UPDATE api_rate_limits SET hits = hits + 1 WHERE ip = ? AND route_key = ?",
            [$ip, $routeKey]
        );

        return $next($request);
    }
}
