<?php

namespace App\Jobs\Notification;

use App\Models\BroadcastCampaign;
use App\Services\Notification\NotificationService;
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 SendBroadcastJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $campaignId;
    public int $batchSize;

    /**
     * Create a new job instance.
     */
    public function __construct(int $campaignId, int $batchSize = 50)
    {
        $this->campaignId = $campaignId;
        $this->batchSize = $batchSize;
        $this->onQueue('notifications');
    }

    /**
     * Execute the job.
     */
    public function handle(NotificationService $notificationService): void
    {
        $campaign = BroadcastCampaign::find($this->campaignId);
        
        if (!$campaign) {
            Log::warning("Broadcast campaign not found: {$this->campaignId}");
            return;
        }

        if (!$campaign->isInProgress()) {
            Log::info("Broadcast campaign not in progress: {$this->campaignId}");
            return;
        }

        try {
            $stats = $notificationService->processCampaign($campaign, $this->batchSize);
            
            Log::info("Broadcast batch processed", [
                'campaign_id' => $this->campaignId,
                'stats' => $stats,
                'progress' => $campaign->fresh()->progress
            ]);

            // If there are still pending recipients, dispatch another job
            if ($campaign->recipients()->pending()->exists()) {
                self::dispatch($this->campaignId, $this->batchSize)
                    ->delay(now()->addMinutes(1)); // 1 minute delay between batches
            }
            
        } catch (\Exception $e) {
            Log::error("Broadcast job failed", [
                'campaign_id' => $this->campaignId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            // Pause campaign on critical errors
            $campaign->pause();
            
            throw $e;
        }
    }

    /**
     * Handle job failure
     */
    public function failed(\Throwable $exception): void
    {
        Log::error("Broadcast job failed permanently", [
            'campaign_id' => $this->campaignId,
            'error' => $exception->getMessage()
        ]);

        $campaign = BroadcastCampaign::find($this->campaignId);
        if ($campaign) {
            $campaign->pause();
        }
    }
}