<?php

namespace App\Jobs\Packages;

use App\Jobs\Concerns\LogsTenantNotifications;
use App\Models\TenantPackage;
use App\Notifications\Packages\TenantPackageEventThresholdNotification;
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 SendTenantPackageEventThresholdWarning implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use LogsTenantNotifications;
    use Queueable;
    use SerializesModels;

    public function __construct(
        public int $tenantPackageId,
        public float $threshold,
        public int $limit,
        public int $used,
    ) {}

    public function handle(): void
    {
        $tenantPackage = TenantPackage::with(['tenant', 'package'])->find($this->tenantPackageId);

        if (! $tenantPackage || ! $tenantPackage->tenant) {
            Log::warning('Tenant package event threshold job skipped', [
                'tenant_package_id' => $this->tenantPackageId,
            ]);

            return;
        }

        $tenant = $tenantPackage->tenant;

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

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

            return;
        }

        $preferences = app(\App\Services\Packages\TenantNotificationPreferences::class);
        if (! $preferences->shouldNotify($tenant, 'event_thresholds')) {
            $this->logNotification($tenant, [
                'type' => 'event_threshold',
                '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('Tenant package event threshold notification skipped due to missing recipients', [
                'tenant_package_id' => $tenantPackage->id,
                'threshold' => $this->threshold,
            ]);

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

            return;
        }

        $this->dispatchToRecipients(
            $tenant,
            $emails,
            'event_threshold',
            function (string $email) use ($tenantPackage) {
                Notification::route('mail', $email)->notify(new TenantPackageEventThresholdNotification(
                    $tenantPackage,
                    $this->threshold,
                    $this->limit,
                    $this->used,
                ));
            },
            $context
        );
    }

    private function context(TenantPackage $tenantPackage): array
    {
        return [
            'tenant_package_id' => $tenantPackage->id,
            'threshold' => $this->threshold,
            'limit' => $this->limit,
            'used' => $this->used,
        ];
    }
}
