<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\WebhookLog;
use App\Services\BayarcashService;

class WebhookController extends Controller
{
    /**
     * Universal webhook endpoint that handles multiple sources
     *
     * @param Request $request
     * @param string|null $source - Optional source identifier in URL
     * @return \Illuminate\Http\JsonResponse
     */
    public function handle(Request $request, $source = null)
    {
        $startTime = microtime(true);

        // Detect source from URL parameter or payload
        $webhookSource = $source ?? $request->input('source', 'custom');

        // Create webhook log entry
        $webhookLog = WebhookLog::create([
            'source' => $webhookSource,
            'event_type' => $request->input('event_type') ?? $request->input('event') ?? 'unknown',
            'webhook_id' => $request->input('webhook_id') ?? $request->input('id'),
            'url' => $request->fullUrl(),
            'method' => $request->method(),
            'headers' => $this->sanitizeHeaders($request->headers->all()),
            'payload' => $request->all(),
            'ip_address' => $request->ip(),
            'status' => 'pending',
        ]);

        try {
            // Log incoming webhook
            \Log::info('Webhook Received', [
                'source' => $webhookSource,
                'event_type' => $webhookLog->event_type,
                'ip' => $request->ip(),
            ]);

            // Route to appropriate handler based on source
            $result = match($webhookSource) {
                'bayarcash' => $this->handleBayarCash($request),
                'custom' => $this->handleCustomWebhook($request),
                default => $this->handleGenericWebhook($request, $webhookSource)
            };

            // Update log with success
            $webhookLog->update([
                'status' => 'success',
                'response' => $result,
                'processed_at' => now(),
            ]);

            $processingTime = round((microtime(true) - $startTime) * 1000, 2);

            \Log::info('Webhook Processed Successfully', [
                'source' => $webhookSource,
                'log_id' => $webhookLog->id,
                'processing_time_ms' => $processingTime,
            ]);

            return response()->json([
                'status' => 'success',
                'message' => 'Webhook processed successfully',
                'webhook_id' => $webhookLog->id,
                'processing_time_ms' => $processingTime,
            ], 200);

        } catch (\Exception $e) {
            // Update log with error
            $webhookLog->update([
                'status' => 'failed',
                'error_message' => $e->getMessage(),
                'processed_at' => now(),
            ]);

            \Log::error('Webhook Processing Failed', [
                'source' => $webhookSource,
                'log_id' => $webhookLog->id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return response()->json([
                'status' => 'error',
                'message' => 'Webhook processing failed',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
                'webhook_id' => $webhookLog->id,
            ], 500);
        }
    }

    /**
     * Handle BayarCash webhook
     */
    protected function handleBayarCash(Request $request)
    {
        $bayarcashService = app(BayarcashService::class);
        $payload = $request->all();

        $result = $bayarcashService->handleCallback($payload);

        if (!$result) {
            throw new \Exception('BayarCash webhook processing failed');
        }

        return [
            'handler' => 'bayarcash',
            'order_number' => $payload['order_number'] ?? null,
            'status' => $payload['status'] ?? null,
        ];
    }

    /**
     * Handle custom webhook from your other websites
     */
    protected function handleCustomWebhook(Request $request)
    {
        $payload = $request->all();

        // Validate required fields
        if (!isset($payload['action'])) {
            throw new \Exception('Missing required field: action');
        }

        // Handle different actions
        return match($payload['action']) {
            'booking.created' => $this->handleBookingCreated($payload),
            'booking.updated' => $this->handleBookingUpdated($payload),
            'booking.cancelled' => $this->handleBookingCancelled($payload),
            'payment.completed' => $this->handlePaymentCompleted($payload),
            'notification.send' => $this->handleNotification($payload),
            default => [
                'handler' => 'custom',
                'action' => $payload['action'],
                'message' => 'Action received but no handler defined',
            ]
        };
    }

    /**
     * Handle generic webhook from any source
     */
    protected function handleGenericWebhook(Request $request, string $source)
    {
        $payload = $request->all();

        \Log::info("Generic Webhook from {$source}", $payload);

        return [
            'handler' => 'generic',
            'source' => $source,
            'payload_received' => true,
            'fields_count' => count($payload),
        ];
    }

    /**
     * Custom action handlers
     */
    protected function handleBookingCreated(array $payload)
    {
        // Your custom logic for booking creation
        \Log::info('Custom Webhook: Booking Created', $payload);

        return [
            'action' => 'booking.created',
            'booking_id' => $payload['booking_id'] ?? null,
            'processed' => true,
        ];
    }

    protected function handleBookingUpdated(array $payload)
    {
        // Your custom logic for booking update
        \Log::info('Custom Webhook: Booking Updated', $payload);

        return [
            'action' => 'booking.updated',
            'booking_id' => $payload['booking_id'] ?? null,
            'processed' => true,
        ];
    }

    protected function handleBookingCancelled(array $payload)
    {
        // Your custom logic for booking cancellation
        \Log::info('Custom Webhook: Booking Cancelled', $payload);

        return [
            'action' => 'booking.cancelled',
            'booking_id' => $payload['booking_id'] ?? null,
            'processed' => true,
        ];
    }

    protected function handlePaymentCompleted(array $payload)
    {
        // Your custom logic for payment completion
        \Log::info('Custom Webhook: Payment Completed', $payload);

        return [
            'action' => 'payment.completed',
            'payment_id' => $payload['payment_id'] ?? null,
            'amount' => $payload['amount'] ?? null,
            'processed' => true,
        ];
    }

    protected function handleNotification(array $payload)
    {
        // Your custom logic for notifications
        \Log::info('Custom Webhook: Notification', $payload);

        return [
            'action' => 'notification.send',
            'message' => $payload['message'] ?? null,
            'processed' => true,
        ];
    }

    /**
     * Sanitize headers for storage (remove sensitive data)
     */
    protected function sanitizeHeaders(array $headers)
    {
        $sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token'];

        foreach ($sensitiveHeaders as $header) {
            if (isset($headers[$header])) {
                $headers[$header] = ['***REDACTED***'];
            }
        }

        return $headers;
    }

    /**
     * Get webhook logs (for admin viewing)
     */
    public function logs(Request $request)
    {
        $source = $request->input('source');
        $status = $request->input('status');

        $logs = WebhookLog::query()
            ->when($source, fn($q) => $q->where('source', $source))
            ->when($status, fn($q) => $q->where('status', $status))
            ->latest()
            ->paginate(50);

        return response()->json($logs);
    }

    /**
     * Get single webhook log detail
     */
    public function show($id)
    {
        $log = WebhookLog::findOrFail($id);

        return response()->json($log);
    }
}
