<?php

namespace App\Service\Push;

use App\Entity\CoastalPoint;
use App\Entity\PushSubscription;
use Doctrine\ORM\EntityManagerInterface;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class PushNotificationService
{
    public function __construct(
        private EntityManagerInterface $em,
        private LoggerInterface $logger,
        #[Autowire('%env(VAPID_PUBLIC_KEY)%')]  private string $vapidPublicKey,
        #[Autowire('%env(VAPID_PRIVATE_KEY)%')] private string $vapidPrivateKey,
        #[Autowire('%env(APP_PUBLIC_URL)%')]     private string $appPublicUrl,
    ) {}

    /**
     * Envoie une alerte push à tous les abonnés d'un CoastalPoint.
     */
    public function notifySpot(CoastalPoint $spot, int $score, string $level): void
    {
        $subscriptions = $this->em->getRepository(PushSubscription::class)
            ->findBy(['coastalPoint' => $spot]);

        if (empty($subscriptions)) {
            return;
        }

        $webPush = new WebPush([
            'VAPID' => [
                'subject'    => $this->appPublicUrl,
                'publicKey'  => $this->vapidPublicKey,
                'privateKey' => $this->vapidPrivateKey,
            ],
        ]);

        $payload = json_encode([
            'title'   => '⚠️ Alerte sargasses — ' . $spot->getName(),
            'body'    => sprintf('Score %d/100 — %s. Vérifiez avant de partir.', $score, ucfirst($level)),
            'url'     => $this->appPublicUrl,
            'spotId'  => (string) $spot->getId(),
        ]) ?: null;

        $expired = [];

        foreach ($subscriptions as $sub) {
            $webPushSub = Subscription::create([
                'endpoint' => $sub->getEndpoint(),
                'keys'     => [
                    'auth'   => $sub->getAuthToken(),
                    'p256dh' => $sub->getP256dhKey(),
                ],
            ]);

            $webPush->queueNotification($webPushSub, $payload);
        }

        foreach ($webPush->flush() as $report) {
            if ($report->isSubscriptionExpired()) {
                // Supprimer les abonnements expirés
                foreach ($subscriptions as $sub) {
                    if ($sub->getEndpoint() === $report->getRequest()->getUri()->__toString()) {
                        $expired[] = $sub;
                    }
                }
            } elseif (!$report->isSuccess()) {
                $this->logger->warning('Push notification failed', [
                    'reason' => $report->getReason(),
                ]);
            }
        }

        foreach ($expired as $sub) {
            $this->em->remove($sub);
        }
        if (!empty($expired)) {
            $this->em->flush();
        }

        $this->logger->info('Push notifications sent', [
            'spot'  => $spot->getName(),
            'count' => count($subscriptions) - count($expired),
        ]);
    }
}
