<?php

namespace App\Http\Middleware;

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

class ContentTypeProtection
{
    /**
     * انواع محتوای مجاز
     */
    protected $allowedContentTypes = [
        'text/html',
        'text/plain',
        'application/json',
        'application/xml',
        'application/x-www-form-urlencoded',
        'multipart/form-data',
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/webp',
        'application/pdf',
        'application/zip',
        'application/x-rar-compressed',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    ];

    /**
     * پسوندهای فایل مجاز
     */
    protected $allowedExtensions = [
        'html', 'htm', 'txt', 'json', 'xml', 'pdf',
        'jpg', 'jpeg', 'png', 'gif', 'webp',
        'zip', 'rar', 'doc', 'docx', 'xls', 'xlsx',
    ];

    public function handle(Request $request, Closure $next): Response
    {
        // بررسی نوع محتوای درخواست
        if ($request->isMethod('POST') || $request->isMethod('PUT')) {
            $contentType = $request->header('Content-Type');

            if (! $this->isValidContentType($contentType)) {
                $this->logInvalidContentType($request, $contentType);

                return response()->json([
                    'message' => 'نوع محتوای درخواست نامعتبر است.',
                    'allowed_types' => $this->allowedContentTypes,
                ], 415);
            }
        }

        $response = $next($request);

        // تنظیم هدرهای امنیتی
        $response->headers->set('X-Content-Type-Options', 'nosniff');

        // تنظیم Content-Type برای پاسخ‌های JSON
        if ($request->wantsJson()) {
            $response->headers->set('Content-Type', 'application/json; charset=UTF-8');
        }

        // بررسی پسوند فایل در URL
        if ($this->hasInvalidFileExtension($request)) {
            $this->logInvalidFileExtension($request);

            return response()->json([
                'message' => 'پسوند فایل نامعتبر است.',
                'allowed_extensions' => $this->allowedExtensions,
            ], 415);
        }

        return $response;
    }

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

        // استخراج نوع اصلی محتوا
        $mainType = strtolower(explode(';', $contentType)[0]);

        return in_array($mainType, $this->allowedContentTypes);
    }

    protected function hasInvalidFileExtension(Request $request): bool
    {
        $path = $request->path();
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));

        if (empty($extension)) {
            return false;
        }

        return ! in_array($extension, $this->allowedExtensions);
    }

    protected function logInvalidContentType(Request $request, ?string $contentType): void
    {
        Log::warning('درخواست با نوع محتوای نامعتبر', [
            'ip' => $request->ip(),
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'content_type' => $contentType,
            'user_agent' => $request->userAgent(),
        ]);
    }

    protected function logInvalidFileExtension(Request $request): void
    {
        Log::warning('درخواست با پسوند فایل نامعتبر', [
            'ip' => $request->ip(),
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'path' => $request->path(),
            'user_agent' => $request->userAgent(),
        ]);
    }
}
