<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;

class ApiRequestValidator
{
    protected $maxRequestsPerMinute = 60;

    protected $maxRequestsPerHour = 1000;

    protected $maxRequestsPerDay = 10000;

    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->is('api/*')) {
            return $next($request);
        }

        $ip = $request->ip();
        $apiKey = $request->header('X-API-Key');

        // بررسی وجود API Key
        if (empty($apiKey)) {
            abort(401, 'کلید API الزامی است.');
        }

        // بررسی اعتبار API Key
        if (! $this->isValidApiKey($apiKey)) {
            abort(401, 'کلید API نامعتبر است.');
        }

        // بررسی محدودیت‌های درخواست
        if ($this->hasExceededRateLimit($ip, $apiKey)) {
            abort(429, 'تعداد درخواست‌های شما بیش از حد مجاز است. لطفاً کمی صبر کنید.');
        }

        // بررسی نسخه API
        $apiVersion = $request->header('X-API-Version');
        if (! $this->isValidApiVersion($apiVersion)) {
            abort(400, 'نسخه API نامعتبر است.');
        }

        // بررسی Content-Type برای درخواست‌های POST/PUT
        if (in_array($request->method(), ['POST', 'PUT']) &&
            ! $this->isValidContentType($request->header('Content-Type'))) {
            abort(415, 'نوع محتوای ارسالی پشتیبانی نمی‌شود.');
        }

        return $next($request);
    }

    protected function isValidApiKey(string $apiKey): bool
    {
        // بررسی اعتبار API Key در دیتابیس یا کش
        return Cache::remember("api_key:{$apiKey}", 3600, function () {
            // اینجا می‌توانید منطق بررسی API Key را پیاده‌سازی کنید
            return true; // فعلاً برای مثال
        });
    }

    protected function hasExceededRateLimit(string $ip, string $apiKey): bool
    {
        $minuteKey = "rate_limit:minute:{$ip}:{$apiKey}";
        $hourKey = "rate_limit:hour:{$ip}:{$apiKey}";
        $dayKey = "rate_limit:day:{$ip}:{$apiKey}";

        // بررسی محدودیت در دقیقه
        $minuteCount = Cache::increment($minuteKey);
        if ($minuteCount === 1) {
            Cache::expire($minuteKey, 60);
        }
        if ($minuteCount > $this->maxRequestsPerMinute) {
            return true;
        }

        // بررسی محدودیت در ساعت
        $hourCount = Cache::increment($hourKey);
        if ($hourCount === 1) {
            Cache::expire($hourKey, 3600);
        }
        if ($hourCount > $this->maxRequestsPerHour) {
            return true;
        }

        // بررسی محدودیت در روز
        $dayCount = Cache::increment($dayKey);
        if ($dayCount === 1) {
            Cache::expire($dayKey, 86400);
        }
        if ($dayCount > $this->maxRequestsPerDay) {
            return true;
        }

        return false;
    }

    protected function isValidApiVersion(?string $version): bool
    {
        if (empty($version)) {
            return false;
        }

        $validVersions = ['1.0', '2.0', '3.0'];

        return in_array($version, $validVersions);
    }

    protected function isValidContentType(?string $contentType): bool
    {
        if (empty($contentType)) {
            return false;
        }

        $validTypes = [
            'application/json',
            'application/x-www-form-urlencoded',
            'multipart/form-data',
        ];

        return in_array($contentType, $validTypes);
    }
}
