<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Hash;

class WebhookAuthMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\JsonResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     */
    public function handle(Request $request, Closure $next)
    {
        try {
            // Get webhook credentials from headers
            $webhookSecret = $request->header('X-Webhook-Secret');
            $webhookUrl = $request->header('X-Webhook-URL');
            $apiKey = $request->header('X-API-Key');

            // Get default credentials from config
            $defaultCredentials = config('webhook.default', []);

            // Check if webhook secret or API key is provided
            if (!$webhookSecret && !$apiKey) {
                Log::warning('Webhook request missing authentication', [
                    'ip' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                    'url' => $request->fullUrl(),
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Webhook secret or API key is required',
                    'error_code' => 'MISSING_AUTH'
                ], 401);
            }

            // Get configured webhook secrets and URLs
            $configuredSecrets = config('webhook.secrets', []);
            $configuredUrls = config('webhook.allowed_urls', []);

            // Validate authentication (API key or webhook secret)
            $isValidAuth = false;
            $isValidUrl = true; // Default to true if no URL validation is configured

            // Check API key authentication
            if ($apiKey && isset($defaultCredentials['api_key'])) {
                $isValidAuth = ($apiKey === $defaultCredentials['api_key']);
            }

            // Check webhook secret authentication
            if (!$isValidAuth && $webhookSecret) {
                foreach ($configuredSecrets as $secret) {
                    if ($secret && Hash::check($webhookSecret, $secret)) {
                        $isValidAuth = true;
                        break;
                    }
                }
            }

            // Validate webhook URL if provided and configured
            if ($webhookUrl && !empty($configuredUrls)) {
                $isValidUrl = in_array($webhookUrl, $configuredUrls);
            }

            if (!$isValidAuth) {
                Log::warning('Webhook request with invalid authentication', [
                    'ip' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                    'url' => $request->fullUrl(),
                    'provided_secret' => $webhookSecret ? substr($webhookSecret, 0, 8) . '...' : null,
                    'provided_api_key' => $apiKey ? substr($apiKey, 0, 8) . '...' : null,
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Invalid webhook secret or API key',
                    'error_code' => 'INVALID_AUTH'
                ], 401);
            }

            if (!$isValidUrl) {
                Log::warning('Webhook request from unauthorized URL', [
                    'ip' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                    'url' => $request->fullUrl(),
                    'provided_url' => $webhookUrl,
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized webhook URL',
                    'error_code' => 'UNAUTHORIZED_URL'
                ], 403);
            }

            // Log successful webhook authentication
            Log::info('Webhook request authenticated successfully', [
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'url' => $request->fullUrl(),
                'webhook_url' => $webhookUrl,
            ]);

            // Add webhook metadata to request for use in controllers
            $request->merge([
                'webhook_authenticated' => true,
                'webhook_url' => $webhookUrl,
                'api_key_used' => $apiKey ? true : false,
                'webhook_secret_used' => $webhookSecret ? true : false,
            ]);

            return $next($request);

        } catch (\Exception $e) {
            Log::error('Webhook authentication error: ' . $e->getMessage(), [
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'url' => $request->fullUrl(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Webhook authentication failed',
                'error_code' => 'AUTH_ERROR'
            ], 500);
        }
    }
}
