<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * XSS Protection Middleware
 * 
 * This middleware provides protection against Cross-Site Scripting (XSS) attacks
 * by sanitizing input data and implementing content filtering.
 */
class XssProtectionMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handle(Request $request, Closure $next): Response
    {
        // Get XSS protection configuration
        $xssConfig = config('security.xss_protection', []);

        if ($xssConfig['enabled'] ?? true) {
            // Sanitize input data
            $this->sanitizeInput($request, $xssConfig);
        }

        $response = $next($request);

        return $response;
    }

    /**
     * Sanitize input data to prevent XSS attacks
     *
     * @param \Illuminate\Http\Request $request
     * @param array $config
     * @return void
     */
    private function sanitizeInput(Request $request, array $config): void
    {
        $input = $request->all();
        $sanitized = $this->recursiveSanitize($input, $config);
        $request->replace($sanitized);
    }

    /**
     * Recursively sanitize array data
     *
     * @param mixed $data
     * @param array $config
     * @return mixed
     */
    private function recursiveSanitize($data, array $config)
    {
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                $data[$key] = $this->recursiveSanitize($value, $config);
            }
            return $data;
        }

        if (is_string($data)) {
            return $this->sanitizeString($data, $config);
        }

        return $data;
    }

    /**
     * Sanitize string data
     *
     * @param string $data
     * @param array $config
     * @return string
     */
    private function sanitizeString(string $data, array $config): string
    {
        // Remove null bytes
        $data = str_replace("\0", '', $data);

        // Strip tags if configured
        if ($config['strip_tags'] ?? true) {
            $allowedTags = $config['allowed_tags'] ?? '';
            $data = strip_tags($data, $allowedTags);
        }

        // Convert special characters to HTML entities
        if ($config['escape_output'] ?? true) {
            $data = htmlspecialchars($data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        }

        // Remove dangerous JavaScript patterns
        $data = $this->removeDangerousPatterns($data);

        return $data;
    }

    /**
     * Remove dangerous JavaScript patterns
     *
     * @param string $data
     * @return string
     */
    private function removeDangerousPatterns(string $data): string
    {
        $dangerousPatterns = [
            '/javascript:/i',
            '/vbscript:/i',
            '/onload=/i',
            '/onerror=/i',
            '/onclick=/i',
            '/onmouseover=/i',
            '/onmouseout=/i',
            '/onfocus=/i',
            '/onblur=/i',
            '/onchange=/i',
            '/onsubmit=/i',
            '/onreset=/i',
            '/onkeydown=/i',
            '/onkeyup=/i',
            '/onkeypress=/i',
            '/<script/i',
            '/<\/script>/i',
            '/<iframe/i',
            '/<\/iframe>/i',
            '/<object/i',
            '/<\/object>/i',
            '/<embed/i',
            '/<\/embed>/i',
            '/<applet/i',
            '/<\/applet>/i',
            '/<meta/i',
            '/<link/i',
            '/<style/i',
            '/<\/style>/i',
            '/expression\s*\(/i',
            '/url\s*\(/i',
            '/import\s*\(/i',
        ];

        foreach ($dangerousPatterns as $pattern) {
            $data = preg_replace($pattern, '', $data);
        }

        return $data;
    }

    /**
     * Check if the request contains potentially malicious content
     *
     * @param string $data
     * @return bool
     */
    private function containsMaliciousContent(string $data): bool
    {
        $maliciousPatterns = [
            '/<script.*?>.*?<\/script>/si',
            '/javascript:/i',
            '/vbscript:/i',
            '/on\w+\s*=/i',
            '/<iframe.*?>/si',
            '/<object.*?>/si',
            '/<embed.*?>/si',
            '/<applet.*?>/si',
            '/expression\s*\(/i',
            '/url\s*\(/i',
            '/import\s*\(/i',
        ];

        foreach ($maliciousPatterns as $pattern) {
            if (preg_match($pattern, $data)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Log suspicious XSS attempts
     *
     * @param \Illuminate\Http\Request $request
     * @param string $suspiciousData
     * @return void
     */
    private function logSuspiciousActivity(Request $request, string $suspiciousData): void
    {
        // Potential XSS attempt detected
    }
}
