<?php

namespace App\Services\Push;

use App\Models\PushSubscription;
use Illuminate\Support\Facades\Log;
use Minishlink\WebPush\MessageSentReport;
use Minishlink\WebPush\Subscription as WebPushSubscription;
use Minishlink\WebPush\WebPush;

class WebPushDispatcher
{
    private ?WebPush $client = null;

    public function send(PushSubscription $subscription, array $payload): ?MessageSentReport
    {
        if (! config('push.enabled')) {
            return null;
        }

        $client = $this->client ??= $this->buildClient();

        if (! $client) {
            return null;
        }

        try {
            $body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
        } catch (\JsonException $exception) {
            Log::channel('notifications')->warning('Unable to encode push payload', [
                'reason' => $exception->getMessage(),
            ]);

            $body = '{}';
        }

        try {
            return $client->sendOneNotification(
                WebPushSubscription::create([
                    'endpoint' => $subscription->endpoint,
                    'publicKey' => $subscription->public_key,
                    'authToken' => $subscription->auth_token,
                    'contentEncoding' => $subscription->content_encoding ?? 'aes128gcm',
                ]),
                $body
            );
        } catch (\Throwable $exception) {
            Log::channel('notifications')->warning('Web push transport error', [
                'event_id' => $subscription->event_id,
                'subscription_id' => $subscription->id,
                'reason' => $exception->getMessage(),
            ]);

            return null;
        }
    }

    private function buildClient(): ?WebPush
    {
        $vapid = config('push.vapid', []);

        if (empty($vapid['public_key']) || empty($vapid['private_key'])) {
            Log::channel('notifications')->warning('Web push skipped because VAPID keys are missing.');

            return null;
        }

        $client = new WebPush([
            'VAPID' => [
                'subject' => $vapid['subject'] ?? config('app.url'),
                'publicKey' => $vapid['public_key'],
                'privateKey' => $vapid['private_key'],
            ],
        ]);

        $client->setDefaultOptions([
            'TTL' => (int) config('push.ttl', 900),
        ]);

        return $client;
    }
}
