<?php

namespace App\Services;

use App\Models\PushSubscription;
use App\Models\User;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;

class WebPushSender
{
    public function isConfigured(): bool
    {
        $vapid = config('webpush.vapid', []);

        return filled($vapid['subject'] ?? null)
            && filled($vapid['public_key'] ?? null)
            && filled($vapid['private_key'] ?? null);
    }

    /**
     * @return array{0: bool, 1: int} Whether any notification was accepted, count of subscriptions attempted
     */
    public function sendToUser(User $user, string $title, string $body, string $url = '/app', string $tag = 'collabs'): array
    {
        if (! $this->isConfigured()) {
            return [false, 0];
        }

        $subs = $user->pushSubscriptions()->get();
        if ($subs->isEmpty()) {
            return [false, 0];
        }

        $webPush = $this->makeClient();
        $payload = json_encode([
            'title' => $title,
            'body' => $body,
            'url' => $url,
            'tag' => $tag,
        ], JSON_THROW_ON_ERROR);

        $anySuccess = false;
        foreach ($subs as $record) {
            $subscription = Subscription::create([
                'endpoint' => $record->endpoint,
                'keys' => [
                    'p256dh' => $record->public_key,
                    'auth' => $record->auth_token,
                ],
                'contentEncoding' => $record->content_encoding ?: 'aes128gcm',
            ]);

            $report = $webPush->sendOneNotification($subscription, $payload);

            if ($report->isSubscriptionExpired()) {
                $record->delete();
            } elseif ($report->isSuccess()) {
                $anySuccess = true;
            }
        }

        return [$anySuccess, $subs->count()];
    }

    public function sendToPushSubscription(PushSubscription $record, string $title, string $body, string $url = '/app', string $tag = 'collabs'): bool
    {
        if (! $this->isConfigured()) {
            return false;
        }

        $webPush = $this->makeClient();
        $payload = json_encode([
            'title' => $title,
            'body' => $body,
            'url' => $url,
            'tag' => $tag,
        ], JSON_THROW_ON_ERROR);

        $subscription = Subscription::create([
            'endpoint' => $record->endpoint,
            'keys' => [
                'p256dh' => $record->public_key,
                'auth' => $record->auth_token,
            ],
            'contentEncoding' => $record->content_encoding ?: 'aes128gcm',
        ]);

        $report = $webPush->sendOneNotification($subscription, $payload);

        if ($report->isSubscriptionExpired()) {
            $record->delete();

            return false;
        }

        return $report->isSuccess();
    }

    private function makeClient(): WebPush
    {
        $vapid = config('webpush.vapid');

        return new WebPush([
            'VAPID' => [
                'subject' => $vapid['subject'],
                'publicKey' => $vapid['public_key'],
                'privateKey' => $vapid['private_key'],
            ],
        ]);
    }
}
