<?php

namespace App\Jobs;

use App\Models\Email;
use App\Models\EmailLog;
use App\Models\EmailLogStatus;
use App\Services\EmailSender;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;

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

    public function __construct(public int $emailLogId)
    {
        //
    }

    public function handle(): void
    {
        $log = EmailLog::query()->find($this->emailLogId);
        if (! $log) {
            return;
        }
        if ($log->status === EmailLogStatus::Sent) {
            return;
        }

        $start = microtime(true);
        $log->status = EmailLogStatus::Sending;
        $log->started_at = now();
        $log->attempt = (int) ($log->attempt ?: 0) + 1;
        $log->save();

        try {
            /** @var EmailSender $sender */
            $sender = app(EmailSender::class);
            $result = $sender->sendFromLog($log);

            $log->status = EmailLogStatus::Sent;
            $log->sent_at = now();
            $log->duration_ms = (int) round((microtime(true) - $start) * 1000);
            $log->save();
        } catch (Throwable $e) {
            $log->status = EmailLogStatus::Failed;
            $log->failed_at = now();
            $log->error_message = $e->getMessage();
            $log->duration_ms = (int) round((microtime(true) - $start) * 1000);
            $log->save();

            if ($log->to_email) {
                Email::query()->where('value', $log->to_email)->update(['failed' => true]);
            }

            throw $e;
        }
    }
}
