<?php

namespace App\Jobs;

use App\Models\SmsMessage;
use App\Services\SmsMessageService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Foundation\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Services\SmsGatewayClient;
use Illuminate\Support\Facades\Log;
use RuntimeException;
use Throwable;

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

    public int $tries = 3;

    public array $backoff = [30, 120, 300];

    public function __construct(public SmsMessage $smsMessage) {}

    public function handle(SmsMessageService $messageService, SmsGatewayClient $client): void
    {
        $message = $this->smsMessage->fresh(['gateway']);
        if (! $message || $message->status === 'sent') {
            return;
        }

        $gateway = $message->gateway;

        if (! $gateway || ! $gateway->api_url) {
            $messageService->markAsFailed($message, 'SMS gateway not configured.');

            return;
        }

        try {
            $response = $client->send($gateway, $message->recipient, $message->message);

            if ($client->succeeded($gateway, $response)) {
                $messageService->markAsSent($message);
                Log::info('SMS message sent successfully.', ['message_id' => $message->id]);
            } else {
                throw new RuntimeException('Gateway response: '.str($response->body())->limit(1000));
            }
        } catch (Throwable $exception) {
            Log::warning('SMS send attempt failed; the queue will retry when attempts remain.', [
                'message_id' => $message->id,
                'attempt' => $this->attempts(),
                'error' => $exception->getMessage(),
            ]);
            throw $exception;
        }
    }

    public function failed(Throwable $exception): void
    {
        $message = $this->smsMessage->fresh();
        if ($message && $message->status !== 'sent') {
            app(SmsMessageService::class)->markAsFailed($message, $exception->getMessage());
        }

        Log::error('SMS delivery failed after all retry attempts.', [
            'message_id' => $this->smsMessage->id,
            'error' => $exception->getMessage(),
        ]);
    }
}
