<?php

namespace App\Jobs\Packages;

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

    public function __construct(
        public int $tenantPackageId,
        public int $daysRemaining,
    ) {}

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

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

            return;
        }

        $tenant = $tenantPackage->tenant;

        $context = [
            'tenant_package_id' => $tenantPackage->id,
            'days_remaining' => $this->daysRemaining,
        ];

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

            return;
        }

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

            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 expiry warning skipped due to missing recipients', [
                'tenant_package_id' => $tenantPackage->id,
                'days_remaining' => $this->daysRemaining,
            ]);

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

            return;
        }

        $this->dispatchToRecipients(
            $tenant,
            $emails,
            'package_expiring',
            function (string $email) use ($tenantPackage) {
                Notification::route('mail', $email)->notify(new TenantPackageExpiringNotification(
                    $tenantPackage,
                    $this->daysRemaining,
                ));
            },
            $context
        );
    }
}
