<?php

namespace App\Jobs;

use App\Models\Contact\Send\EmailSend;
use App\Services\SendGridEmailService;
use App\Support\SendStatus;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Throwable;

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

    public int $tries = 5;
    public int $timeout = 30;

    public function __construct(public EmailSend $emailSend) {
    }

    public function handle(SendGridEmailService $mailjet): void {
        if ($this->emailSend->status === SendStatus::SENT) {
            return;
        }

        $this->emailSend->update([
            'status' => SendStatus::SENDING,
            'attempts' => $this->emailSend->attempts + 1,
            'last_attempt_at' => now(),
            'provider' => 'sendgrid',
        ]);

        try {
            // Resolve attachments: entries with a 'path' key are read from storage
            // here (just-in-time) so base64 blobs are never persisted to the DB.
            $attachments = collect($this->emailSend->attachments ?? [])
                ->map(function (array $a): array {
                    if (isset($a['path'])) {
                        $a['content'] = base64_encode(Storage::get($a['path']));
                        unset($a['path']);
                    }
                    return $a;
                })
                ->all();

            $response = $mailjet->send([
                'to_email'      => $this->emailSend->to_email,
                'to_name'       => $this->emailSend->to_name,
                'from_email'    => $this->emailSend->from_email,
                'from_name'     => $this->emailSend->from_name,
                'reply_to'      => $this->emailSend->reply_to,
                'subject'       => $this->emailSend->subject,
                'html'          => $this->emailSend->html_body,
                'text'          => $this->emailSend->text_body,
                'template_id'   => $this->emailSend->template,
                'template_data' => $this->emailSend->template_data,
                'attachments'   => $attachments,
            ]);

            // Free the encoded attachment content as soon as the call is done
            unset($attachments);

            // SendGrid returns 202 Accepted with no body; message ID is in the X-Message-Id header
            $messageId = $response['headers']['X-Message-Id'][0]
                ?? null;

            $this->emailSend->update([
                'provider_message_id' => $messageId,
                'provider_response' => $response,
            ]);

            if($messageId) {
                $this->emailSend->update([
                    'status' => SendStatus::SENT,
                    'sent_at' => now(),
                ]);
            }

        } catch (Throwable $e) {
            $this->emailSend->update([
                'status' => SendStatus::FAILED,
                'error_message' => $e->getMessage(),
            ]);

            throw $e;
        }
    }
}
