<?php
declare(strict_types=1);

namespace App\Framework\Firewall;

use App\Framework\Exception\SecurityEvent\InputSqlInjectionAttemptEvent;
use App\Framework\Exception\SecurityException;
use App\Framework\Http\HttpMiddleware;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\MiddlewarePriority;
use App\Framework\Http\MiddlewarePriorityAttribute;
use App\Framework\Http\RequestStateManager;

#[MiddlewarePriorityAttribute(MiddlewarePriority::SECURITY)]
final readonly class FirewallMiddleware implements HttpMiddleware
{

    public function __invoke(MiddlewareContext $context, callable $next, RequestStateManager $stateManager): MiddlewareContext
    {
        $request = $context->request;

        # Bot Blocking

        $userAgent = $request->server->getUserAgent();

        #shoud not be empty:
        if($userAgent === '') {
            # Bot detected
        }
        $bots = ['Scrapy'];
        foreach($bots as $bot) {
            if(str_contains($userAgent, $bot)) {
                $bot = true;
            }
        }



        $patterns = [
            '/UNION\s+SELECT/i',
            '/SELECT.*FROM/i',
            '/INSERT\s+INTO/i',
            '/<script.*?>/i',
            '/javascript:/i',
            '/\.\.\//',
            '/%00/',
        ];

        $dataSources = [
            $request->path,
            $request->server->getQueryString(),
            $request->body,
        ];

        foreach ($dataSources as $input) {
            foreach ($patterns as $pattern) {
                if (preg_match($pattern, $input)) {
                    throw new SecurityException(new InputSqlInjectionAttemptEvent('field'));
                }
            }
        }

        return $next($context);
    }
}
