<?php

namespace App\Jobs\Packages;

use App\Jobs\Concerns\LogsTenantNotifications;
use App\Models\EventPackage;
use App\Notifications\Packages\EventPackageGuestLimitNotification;
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;
use Illuminate\Support\Facades\Notification;

class SendEventPackageGuestLimitNotification implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use LogsTenantNotifications;
    use Queueable;
    use SerializesModels;

    public function __construct(
        public int $eventPackageId,
        public int $limit,
    ) {}

    public function handle(): void
    {
        $eventPackage = EventPackage::with(['event', 'package', 'event.tenant'])->find($this->eventPackageId);

        if (! $eventPackage) {
            Log::warning('Guest limit job skipped; event package missing', [
                'event_package_id' => $this->eventPackageId,
            ]);

            return;
        }

        $tenant = $eventPackage->event?->tenant;
        if (! $tenant) {
            return;
        }

        $context = $this->context($eventPackage);

        if ($this->isDuplicateNotification($tenant, 'guest_limit', $context, ['event_package_id', 'limit'])) {
            $this->logNotification($tenant, [
                'type' => 'guest_limit',
                'status' => 'skipped',
                'context' => array_merge($context, ['reason' => 'duplicate']),
            ]);

            return;
        }

        $preferences = app(\App\Services\Packages\TenantNotificationPreferences::class);
        if (! $preferences->shouldNotify($tenant, 'guest_limits')) {
            $this->logNotification($tenant, [
                'type' => 'guest_limit',
                'status' => 'skipped',
                'context' => $context,
            ]);

            return;
        }

        $emails = collect([
            $tenant->contact_email,
            $tenant->user?->email,
        ])->filter(fn ($email) => is_string($email) && filter_var($email, FILTER_VALIDATE_EMAIL))
            ->unique();

        if ($emails->isEmpty()) {
            Log::info('Guest limit notification skipped due to missing recipients', [
                'event_package_id' => $eventPackage->id,
            ]);

            $this->logNotification($tenant, [
                'type' => 'guest_limit',
                'status' => 'skipped',
                'context' => array_merge($context, ['reason' => 'no_recipient']),
            ]);

            return;
        }

        $this->dispatchToRecipients(
            $tenant,
            $emails,
            'guest_limit',
            function (string $email) use ($eventPackage) {
                Notification::route('mail', $email)->notify(new EventPackageGuestLimitNotification(
                    $eventPackage,
                    $this->limit,
                ));
            },
            $context
        );
    }

    private function context(EventPackage $eventPackage): array
    {
        return [
            'event_package_id' => $eventPackage->id,
            'event_id' => $eventPackage->event_id,
            'limit' => $this->limit,
        ];
    }
}
