<?php

namespace App\Http\Controllers;

use App\Exceptions\CourierException;
use App\Services\Courier\CourierSettingsService;
use App\Services\Courier\CourierTrackingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class CourierWebhookController extends Controller
{
    public function __construct(
        private readonly CourierSettingsService $courierSettingsService,
        private readonly CourierTrackingService $courierTrackingService
    ) {
    }

    public function handleSteadFastWebhook(Request $request): JsonResponse
    {
        $providerConfig = $this->courierSettingsService->getProviderConfig('steadfast');
        $configuredToken = trim((string) data_get($providerConfig, 'webhook_bearer_token'));

        if (blank($configuredToken)) {
            return response()->json([
                'status' => 'error',
                'message' => 'SteadFast webhook bearer token is not configured.',
            ], 503);
        }

        $incomingToken = trim((string) $request->bearerToken());

        if (blank($incomingToken) || ! hash_equals($configuredToken, $incomingToken)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Unauthorized',
            ], 401);
        }

        $payload = $request->all();
        $notificationType = str_replace('-', '_', strtolower(trim((string) data_get($payload, 'notification_type', 'delivery_status'))));
        if (filled(data_get($payload, 'notification_type'))) {
            $payload['notification_type'] = $notificationType;
        }

        $validator = Validator::make($payload, [
            'notification_type' => 'nullable|string|in:delivery_status,tracking_update,settlement_update,cod_collection,cod_settlement,payment_update',
            'consignment_id' => 'nullable',
            'invoice' => 'nullable|string|max:191',
            'cod_amount' => 'nullable',
            'collected_amount' => 'nullable',
            'cod_collected_amount' => 'nullable',
            'settled_amount' => 'nullable',
            'status' => 'nullable|string|max:100',
            'delivery_status' => 'nullable|string|max:100',
            'collection_status' => 'nullable|string|max:100',
            'cod_collection_status' => 'nullable|string|max:100',
            'settlement_status' => 'nullable|string|max:100',
            'paid_status' => 'nullable|string|max:100',
            'payment_status' => 'nullable|string|max:100',
            'delivery_charge' => 'nullable',
            'return_charge' => 'nullable',
            'cod_charge' => 'nullable',
            'tracking_message' => 'nullable|string|max:1000',
            'tracking_code' => 'nullable|string|max:191',
            'tracking_id' => 'nullable|string|max:191',
            'collection_date' => 'nullable',
            'payment_date' => 'nullable',
            'settlement_date' => 'nullable',
            'paid_at' => 'nullable',
            'settlement_reference' => 'nullable|string|max:191',
            'payment_reference' => 'nullable|string|max:191',
            'transaction_id' => 'nullable|string|max:191',
            'trx_id' => 'nullable|string|max:191',
            'updated_at' => 'nullable',
            'event_id' => 'nullable|string|max:255',
            'rider' => 'nullable|array',
            'rider.id' => 'nullable|max:255',
            'rider.name' => 'nullable|string|max:255',
            'rider.phone' => 'nullable|string|max:50',
            'rider.mobile' => 'nullable|string|max:50',
            'delivery_man' => 'nullable|array',
            'delivery_man.id' => 'nullable|max:255',
            'delivery_man.name' => 'nullable|string|max:255',
            'delivery_man.phone' => 'nullable|string|max:50',
            'delivery_man.mobile' => 'nullable|string|max:50',
            'rider_id' => 'nullable|max:255',
            'rider_name' => 'nullable|string|max:255',
            'rider_phone' => 'nullable|string|max:50',
            'rider_mobile' => 'nullable|string|max:50',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid webhook payload.',
                'errors' => $validator->errors(),
            ], 422);
        }

        if (
            blank(data_get($payload, 'consignment_id'))
            && blank(data_get($payload, 'tracking_code'))
            && blank(data_get($payload, 'tracking_id'))
            && blank(data_get($payload, 'invoice'))
        ) {
            return response()->json([
                'status' => 'error',
                'message' => 'Webhook payload must include consignment id, tracking code, or invoice.',
            ], 422);
        }

        try {
            if ($notificationType === 'tracking_update') {
                $shipment = $this->courierTrackingService->recordTrackingWebhook($payload, 'steadfast');

                return response()->json([
                    'status' => 'success',
                    'message' => 'Webhook received successfully.',
                    'order_id' => $shipment->order_id,
                    'shipment_id' => $shipment->id,
                ]);
            }

            $shipment = $this->courierTrackingService->syncFromWebhook($payload, 'steadfast');

            return response()->json([
                'status' => 'success',
                'message' => 'Webhook received successfully.',
                'order_id' => $shipment->order_id,
                'shipment_id' => $shipment->id,
                'courier_status' => $shipment->courier_status,
            ]);
        } catch (CourierException $exception) {
            return response()->json([
                'status' => 'error',
                'message' => $exception->getMessage(),
            ], 422);
        } catch (\Throwable $throwable) {
            Log::error('SteadFast webhook processing failed.', [
                'message' => $throwable->getMessage(),
                'payload' => $payload,
            ]);

            return response()->json([
                'status' => 'error',
                'message' => 'Webhook processing failed.',
            ], 500);
        }
    }
}
