<?php


namespace App\Console\Commands;

use App\Models\MailQueue;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;

class ProcessMailQueue extends Command
{
    protected $signature = 'app:process-mail-queue';
    protected $description = 'Process mail queue';

    public function handle()
    {
        while (true) {

            $jobs = MailQueue::where(function ($q) {
                $q->where('status', 'pending')
                    ->orWhere(function ($q) {
                        $q->where('status', 'processing')
                            ->where('updated_at', '<', now()->subMinutes(2));
                    });
            })
                ->where(function ($q) {
                    $q->whereNull('available_at')
                        ->orWhere('available_at', '<=', now());
                })
                ->orderBy('created_at')
                ->limit(10)
                ->get();

            foreach ($jobs as $mail) {

                // 🔥 ATOMIC LOCK
                $updated = MailQueue::where('id', $mail->id)
                    ->where(function ($q) {
                        $q->where('status', 'pending')
                            ->orWhere(function ($q) {
                                $q->where('status', 'processing')
                                    ->where('updated_at', '<', now()->subMinutes(2));
                            });
                    })
                    ->limit(1)
                    ->update([
                        'status' => 'processing',
                        'updated_at' => now(),
                    ]);

                if (!$updated) {
                    continue;
                }

                try {

                    app()->setLocale($mail->locale);

                    $html = view('emails.' . $mail->template, $mail->meta)->render();

                    Mail::html($html, function ($message) use ($mail) {
                        $message->to($mail->to)
                            ->subject($mail->subject ?? 'Mail');
                    });

                    $mail->update([
                        'sent_at' => now(),
                        'status' => 'sent',
                        'error' => null
                    ]);

                    usleep(500000);

                } catch (\Throwable $e) {

                    $tries = $mail->tries + 1;
                    $delay = 30 * $tries;

                    $status = $tries >= $mail->max_tries ? 'failed' : 'pending';

                    $mail->update([
                        'tries' => $tries,
                        'status' => $status,
                        'error' => $e->getMessage(),
                        'available_at' => $status === 'pending'
                            ? now()->addSeconds($delay)
                            : null,
                    ]);
                }
            }

            // 🔥 dynamisches sleep
            if ($jobs->isEmpty()) {
                usleep(1000000); // idle
            } else {
                usleep(200000); // busy
            }
        }
    }
}
//
//namespace App\Console\Commands;
//
//use App\Models\MailQueue;
//use Illuminate\Console\Attributes\Description;
//use Illuminate\Console\Attributes\Signature;
//use Illuminate\Console\Command;
//use Illuminate\Support\Facades\Mail;
//
//#[Signature('app:process-mail-queue')]
//#[Description('Command description')]
//class ProcessMailQueue extends Command
//{
//    /**
//     * Execute the console command.
//     */
//    public function handle()
//    {
//        while (true) {
//
//            $jobs = MailQueue::where(function ($q) {
//                $q->where('status', 'pending')
//                    ->orWhere(function ($q) {
//                        $q->where('status', 'processing')
//                            ->where('updated_at', '<', now()->subMinutes(2));
//                    });
//            })
//                ->limit(10)
//                ->orderBy('created_at')
//                ->get();
//
//            $jobs->each(function ($mail) {
//
//                    // 🔥 LOCK setzen
//                    $updated = MailQueue::where('id', $mail->id)
//                        ->where(function ($q) {
//                            $q->where('status', 'pending')
//                                ->orWhere(function ($q) {
//                                    $q->where('status', 'processing')
//                                        ->where('updated_at', '<', now()->subMinutes(2));
//                                });
//                        })
//                        ->update([
//                            'status' => 'processing',
//                            'updated_at' => now(),
//                        ]);
//
//                    // wenn schon verarbeitet → skip
//                    if (!$updated) return;
//
//                    $mail->refresh();
//
//                    try {
//
//                        app()->setLocale($mail->locale);
//
//                        $html = view('emails.' . $mail->template, $mail->meta)->render();
//
//                        Mail::html($html, function ($message) use ($mail) {
//                            $message->to($mail->to)
//                                ->subject($mail->subject ?? 'Mail');
//                        });
//
//                        $mail->update([
//                            'sent_at' => now(),
//                            'status' => 'sent',
//                            'error' => null
//                        ]);
//
//                    } catch (\Throwable $e) {
//
//                        $tries = $mail->tries + 1;
//                        $delay = 30 * $tries;
//
//                        $status = $tries >= $mail->max_tries ? 'failed' : 'pending';
//
//                        $mail->update([
//                            'tries' => $tries,
//                            'status' => $status,
//                            'error' => $e->getMessage(),
//                            'available_at' => $status === 'pending'
//                                ? now()->addSeconds($delay)
//                                : null,
//                        ]);
//                    }
//
//                });
//
//            if ($jobs->isEmpty()) {
//                usleep(1000000); // 1s
//            } else {
//                usleep(200000); // 0.2s
//            }
//        }
//    }
//}
