<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Mercure\Security;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Context\UserContext;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Mercure\ChannelGenerator;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Notification\Enum\PushChannel;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mercure\Jwt\TokenProviderInterface;

readonly class JWTSubscriberProvider implements TokenProviderInterface
{
    public function __construct(
        /** @var non-empty-string $mercureSubscriberJwtKey */
        #[Autowire(env: 'MERCURE_SUBSCRIBER_JWT_KEY')]
        private string $mercureSubscriberJwtKey,
        private Security $security, private RequestStack $request)
    {
    }

    public function getJwt(): string
    {
        $subscribe = [];
        if (UserContext::$identifierWindowId) {
            $subscribe[] = ChannelGenerator::subscriptionRoute(UserContext::$identifierWindowId);
        }

        if ($this->request->getSession()->isStarted() && UserContext::$identifierSession) {
            $subscribe[] = ChannelGenerator::subscriptionRoute(UserContext::$identifierSession);
        }

        if ($this->security->getUser() && UserContext::$identifierUserId) {
            $subscribe[] = ChannelGenerator::subscriptionRoute(UserContext::$identifierUserId);
        }

        $config = Configuration::forSymmetricSigner(new Sha256(), InMemory::plainText($this->mercureSubscriberJwtKey));

        return $config->builder()->withClaim('mercure', ['subscribe' => $subscribe])
            ->getToken($config->signer(), $config->signingKey())->toString();
    }
}
