<?php

namespace App\Services;

use App\Models\PushSubscription;
use App\Models\SpaceMember;
use Illuminate\Support\Collection;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;

class WebPushService
{
    public function sendToSpace(string $spaceId, array $payload, ?int $excludeUserId = null): void
    {
        $vapidPublic = (string) config('services.webpush.public_key', '');
        $vapidPrivate = (string) config('services.webpush.private_key', '');
        if ($vapidPublic === '' || $vapidPrivate === '') {
            return;
        }

        $memberUserIds = SpaceMember::query()
            ->where('space_id', $spaceId)
            ->when($excludeUserId !== null, fn ($q) => $q->where('user_id', '!=', $excludeUserId))
            ->pluck('user_id')
            ->values();

        if ($memberUserIds->count() === 0) {
            return;
        }

        /** @var Collection<int, PushSubscription> $subs */
        $subs = PushSubscription::query()
            ->whereIn('user_id', $memberUserIds->all())
            ->get();

        if ($subs->count() === 0) {
            return;
        }

        $webPush = new WebPush([
            'VAPID' => [
                'subject' => (string) (config('app.url') ?: ''),
                'publicKey' => $vapidPublic,
                'privateKey' => $vapidPrivate,
            ],
        ]);

        $json = json_encode($payload);
        if ($json === false) {
            return;
        }

        foreach ($subs as $s) {
            $subscription = Subscription::create([
                'endpoint' => $s->endpoint,
                'keys' => [
                    'p256dh' => $s->p256dh,
                    'auth' => $s->auth,
                ],
            ]);

            // Best effort; failures are handled by flush().
            $webPush->queueNotification($subscription, $json);
        }

        foreach ($webPush->flush() as $report) {
            if (! $report->isSuccess() && $report->getResponse() && $report->getResponse()->getStatusCode() === 410) {
                // Subscription is gone; we could delete it, but keep it simple / safe.
            }
        }
    }
}

