<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class XssMiddleware
{
    /**
     * Request paths that should bypass XSS sanitization (e.g. webhook payloads,
     * raw SDK callbacks where altering the body would break signature checks).
     *
     * @var array<int, string>
     */
    protected array $except = [
        'whatsapp/webhook/*',
        'telegram/webhook/*',
        'messenger/webhook/*',
        'whatsapp/web/webhook/*',
        'sms/dlr/*',
        'sms/inbound/*',
        'stripe/webhook',
        'stripe/webhook/*',
    ];

    public function handle(Request $request, Closure $next)
    {
        if ($this->shouldSkip($request)) {
            return $next($request);
        }

        $userInput = $request->all();
        array_walk_recursive($userInput, function (&$value) {
            if (! is_string($value)) {
                return;
            }

            $value = $this->clean($value);
        });
        $request->merge($userInput);

        return $next($request);
    }

    protected function shouldSkip(Request $request): bool
    {
        foreach ($this->except as $pattern) {
            if ($request->is($pattern)) {
                return true;
            }
        }

        return false;
    }

    protected function clean(string $value): string
    {
        $patterns = [
            '#<script\b[^>]*>.*?</script\s*>#is',
            '#<iframe\b[^>]*>.*?</iframe\s*>#is',
            '#<object\b[^>]*>.*?</object\s*>#is',
            '#<embed\b[^>]*>.*?</embed\s*>#is',
            '#<\s*script\b[^>]*/?\s*>#i',
            '#&lt;script\b.*?&gt;.*?&lt;/script&gt;#is',
            '#\s*on[a-z]+\s*=\s*"[^"]*"#i',
            '#\s*on[a-z]+\s*=\s*\'[^\']*\'#i',
            '#\s*on[a-z]+\s*=\s*[^\s>]+#i',
            '#javascript\s*:#i',
            '#vbscript\s*:#i',
            '#data\s*:\s*text/html#i',
        ];

        return preg_replace($patterns, '', $value) ?? $value;
    }
}
