<?php

namespace App\Jobs;

use App\Models\SystemNotificationCampaign;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class ProcessSystemNotificationCampaign implements ShouldQueue
{
    use Queueable;

    public function __construct(public int $campaignId) {}

    public function handle(): void
    {
        $campaign = SystemNotificationCampaign::find($this->campaignId);
        if (! $campaign || $campaign->status === 'completed') {
            return;
        }

        $campaign->update(['status' => 'processing']);
        $query = $this->audienceQuery($campaign);
        $campaign->update(['estimated_recipients' => (clone $query)->count()]);

        $query->select('users.id')->chunkById(500, function ($users) use ($campaign) {
            $now = now();
            DB::table('user_notifications')->insertOrIgnore($users->map(fn ($user) => [
                'uuid' => Str::uuid(),
                'tenant_id' => $campaign->tenant_id,
                'user_id' => $user->id,
                'system_notification_campaign_id' => $campaign->id,
                'title' => $campaign->title,
                'body' => $campaign->body,
                'action_url' => $campaign->action_url,
                'icon' => $campaign->icon,
                'created_at' => $now,
                'updated_at' => $now,
            ])->all());
            $campaign->increment('processed_recipients', $users->count());
        });
        $campaign->update(['status' => 'completed', 'completed_at' => now()]);
    }

    private function audienceQuery(SystemNotificationCampaign $campaign)
    {
        $audience = $campaign->audience;

        return User::query()
            ->whereNull('deleted_at')
            ->when($audience['statuses'] ?? null, fn ($q, $values) => $q->whereIn('status', $values))
            ->when(! $campaign->tenant_id && ($audience['access_levels'] ?? null), fn ($q) => $q->whereIn('access_level', $audience['access_levels']))
            ->when($audience['user_ids'] ?? null, fn ($q, $values) => $q->whereIn('id', $values))
            ->when($campaign->tenant_id, fn ($q, $tenantId) => $q->whereHas('userTenants', fn ($x) => $x
                ->where('tenant_id', $tenantId)
                ->when($audience['access_levels'] ?? null, fn ($roleQuery, $roles) => $roleQuery->whereIn('role', $roles))));
    }
}
