<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class DispatchWebhookJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public string $eventId,
        public string $subscriptionId
    ) {}

    public function handle()
    {

        echo 'passou por aqui bbg';

        $event = DB::table('webhook_events')->findOrFail($this->eventId);
        $sub   = DB::table('webhook_subcribers')->findOrFail($this->subscriptionId);

        $delivery = DB::table('webhook_deliveries')->insert([
            'event_id' => $event->id,
            'webhook_subscription_id' => $sub->id,
        ]);

        $deliveryId = 'del_' . Str::uuid();

        DB::table('webhook_deliveries')->insertGetId([
            'delivery_uuid' => $deliveryId,
            'event_id' => $event->id,
            'subscriber_id' => $sub->id,
            'event_type' => $event->event_type,
            'payload' => json_encode($event->payload),
        ]);

        $delivery = DB::table('webhook_deliveries')->where('delivery_uuid', $deliveryId)->first();

        $payload = [
            'id'   => $event->id,
            'type' => $event->event_type,
            'data' => $event->payload
        ];

        $timestamp = time(); // ou Carbon::now()->timestamp
        $signedPayload = $timestamp . '.' . json_encode($payload);

        //Assinando o payload com o segredo do webhook para garantir a autenticidade da requisição
        $signature = hash_hmac(
            'sha256',
            $signedPayload,
            $sub->webhook_secret
        );

        try {
            // Enviando a requisição para o endpoint do assinante com os headers de autenticação e o payload
            $response = Http::timeout(10)
                ->withHeaders([
                    'X-Webhook-Signature' => $signature,
                    'X-Webhook-Timestamp' => $timestamp,
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json'
                ])
                ->post($sub->callback_url, $payload);

            $delivery->update([
                'status' => $response->successful() ? 'SENT' : 'FAILED',
                'partner_response_body' => $response->body(),
                'partner_response_code' => $response->status(),
                'attempts' => $delivery->attempts + 1,
                'last_attempt_at' => now()
            ]);

            if (!$response->successful()) {
                throw new \Exception('Webhook failed.');
            }
        } catch (\Exception $e) {

            $delivery->update([
                'status' => 'FAILED',
                'partner_response_body' => $e->getMessage(),
                'partner_response_code' => 0,
                'attempts' => $delivery->attempts + 1,
                'last_attempt_at' => now()
            ]);

            // retry automático para tentativas de entrega falhadas, limitando o número de tentativas para evitar loops infinitos
            if ($delivery->attempts < 5) {
                DispatchWebhookJob::dispatch($event->id, $sub->id)
                    ->delay(now()->addMinutes(2)); // re-tentativa após 2 minutos
            }
        }
    }
}
