<?php

namespace App\Jobs;

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\Mail;

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

    public function __construct(public int $messageId) {}

    public function handle()
    {
        $msg = \App\Models\EmailMessage::with(['recipients', 'attachments'])->findOrFail($this->messageId);

        $msg->update(['status' => 'processing']);
        try {
            $attachments = $msg->attachments
                ->map(fn($a) => [
                    'disk' => $a->disk,
                    'path' => $a->path,
                    'name' => $a->name ?? basename($a->path),
                ])
                ->values()->all();
        } catch (\Throwable $e) {
            $msg->update(['status' => 'failed', 'error_message' => $e->getMessage()]);
        }


        foreach ($msg->recipients as $r) {
            if (in_array($r->status, ['sent', 'failed'])) continue;

            try {

                $mailable = new \App\Mail\GenericMail(
                    $msg->subject,
                    $msg->content_html,
                    $attachments
                );

                Mail::to($r->email_address)->send($mailable);

                $r->update(['status' => 'sent', 'sent_at' => now(), 'error_message' => null]);
            } catch (\Throwable $e) {
                $r->update(['status' => 'failed', 'error_message' => $e->getMessage()]);
            }
        }
        $total = $msg->recipients()->count();
        $sent = $msg->recipients()->where('status', 'sent')->count();
        $failed = $msg->recipients()->where('status', 'failed')->count();

        $newStatus = 'draft';
        if ($total === 0) {
            $newStatus = 'draft';
        } elseif ($sent === $total) {
            $newStatus = 'sent';
        } elseif ($sent > 0 && $failed > 0) {
            $newStatus = 'partial';
        } else {
            $newStatus = 'failed';
        }

        $msg->update([
            'status' => $newStatus,
            'sent_at' => $sent > 0 ? now() : $msg->sent_at,
        ]);
    }
}
