<?php

namespace App\Http\Middleware;

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

class BlockApiToolsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        // Check if API tool blocking is enabled
        if (!config('api_security.block_api_tools_in_production')) {
            return $next($request);
        }

        // Skip blocking for external API routes - they use API key authentication
        if ($request->is('api/external*')) {
            return $next($request);
        }

        // Only block in production environment
        if (app()->environment('production')) {
            $userAgent = strtolower($request->header('User-Agent', ''));
            $clientIp = $request->ip();

            // Check if request has valid API key - bypass blocking for external systems
            if ($this->hasValidApiKey($request)) {
                return $next($request);
            }

            // Check if IP is in allowed list
            $allowedIps = config('api_security.allowed_ips', []);
            if (!empty($allowedIps) && in_array($clientIp, $allowedIps)) {
                return $next($request);
            }

            // Check if User-Agent is in allowed list
            $allowedUserAgents = config('api_security.allowed_user_agents', []);
            foreach ($allowedUserAgents as $allowedAgent) {
                if (str_contains($userAgent, strtolower($allowedAgent))) {
                    return $next($request);
                }
            }

            // Check if the User-Agent matches any blocked patterns
            $blockedUserAgents = config('api_security.blocked_user_agents', []);
            foreach ($blockedUserAgents as $blockedAgent) {
                if (str_contains($userAgent, $blockedAgent)) {
                    return response()->json([
                        'success' => false,
                        'message' => config('api_security.blocked_message', 'API access is restricted in production environment. Please use the web interface.'),
                        'error' => 'API_TOOLS_BLOCKED'
                    ], 403);
                }
            }

            // Additional check for requests without proper browser User-Agent
            // This catches tools that might not be in our list but don't look like browsers
            if ($this->isSuspiciousUserAgent($userAgent)) {
                return response()->json([
                    'success' => false,
                    'message' => config('api_security.blocked_message', 'API access is restricted in production environment. Please use the web interface.'),
                    'error' => 'API_TOOLS_BLOCKED'
                ], 403);
            }
        }

        return $next($request);
    }

    /**
     * Check if the User-Agent looks suspicious (not a real browser)
     */
    private function isSuspiciousUserAgent(string $userAgent): bool
    {
        $minLength = config('api_security.min_user_agent_length', 10);
        
        // If User-Agent is empty or very short, it's suspicious
        if (empty($userAgent) || strlen($userAgent) < $minLength) {
            return true;
        }

        // Check for common browser patterns
        $browserPatterns = [
            'mozilla',
            'chrome',
            'safari',
            'firefox',
            'edge',
            'opera',
            'webkit',
            'gecko',
            'trident',
            'msie',
        ];

        $hasBrowserPattern = false;
        foreach ($browserPatterns as $pattern) {
            if (str_contains($userAgent, $pattern)) {
                $hasBrowserPattern = true;
                break;
            }
        }

        // If no browser pattern is found, it's likely an API tool
        return !$hasBrowserPattern;
    }

    /**
     * Check if the request has a valid API key for external system access
     */
    private function hasValidApiKey(Request $request): bool
    {
        // Check for API key in headers (X-API-Key, Authorization Bearer, or API-Key)
        $apiKey = $request->header('X-API-Key') 
                ?? $request->header('API-Key')
                ?? $this->extractBearerToken($request->header('Authorization'));

        if (!$apiKey) {
            return false;
        }

        // Get valid API keys from configuration
        $validApiKeys = config('api_security.valid_api_keys', []);
        
        // If no API keys configured, return false
        if (empty($validApiKeys)) {
            return false;
        }

        // Check if the provided API key is valid
        return in_array($apiKey, $validApiKeys);
    }

    /**
     * Extract Bearer token from Authorization header
     */
    private function extractBearerToken(?string $authorization): ?string
    {
        if (!$authorization) {
            return null;
        }

        if (preg_match('/Bearer\s+(.*)$/i', $authorization, $matches)) {
            return $matches[1];
        }

        return null;
    }
}
