<?php

namespace App\Jobs;

use App\Services\NotificationService;
use App\Models\Notification;
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\Log;

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

    protected $notificationId;
    protected $maxAttempts = 3;
    protected $timeout = 60;

    /**
     * Create a new job instance.
     *
     * @param int $notificationId
     * @return void
     */
    public function __construct(int $notificationId)
    {
        $this->notificationId = $notificationId;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle(NotificationService $notificationService)
    {
        try {
            $notification = Notification::find($this->notificationId);

            if (!$notification) {
                Log::warning("Scheduled notification not found: {$this->notificationId}");
                return;
            }

            if ($notification->status !== 'scheduled') {
                Log::warning("Notification {$this->notificationId} is not in scheduled status: {$notification->status}");
                return;
            }

            if ($notification->scheduled_at && $notification->scheduled_at->isFuture()) {
                // Reschedule for later
                $this->dispatchLater($notification->scheduled_at->diffInSeconds(now()), new self($notification->id));
                Log::info("Rescheduling notification {$this->notificationId} for {$notification->scheduled_at}");
                return;
            }

            // Send the notification
            $success = $notificationService->sendNotification($notification);

            if ($success) {
                Log::info("Successfully sent scheduled notification: {$this->notificationId}");
            } else {
                Log::error("Failed to send scheduled notification: {$this->notificationId}");
                $this->fail(new \Exception('Failed to send notification'));
            }

        } catch (\Exception $e) {
            Log::error("Exception in SendScheduledNotification job: " . $e->getMessage(), [
                'notification_id' => $this->notificationId,
                'exception' => $e
            ]);
            throw $e;
        }
    }

    /**
     * Handle a job failure.
     *
     * @param  \Throwable  $exception
     * @return void
     */
    public function failed(\Throwable $exception)
    {
        Log::error("SendScheduledNotification job failed for notification {$this->notificationId}: " . $exception->getMessage());

        // Update notification status to failed
        $notification = Notification::find($this->notificationId);
        if ($notification) {
            $notification->update(['status' => 'failed']);
        }
    }

    /**
     * Get the tags that should be assigned to the job.
     *
     * @return array
     */
    public function tags()
    {
        return ['notification', 'scheduled', 'notification:' . $this->notificationId];
    }
}
