<?php

declare(strict_types=1);

namespace App\Administration\Infrastructure\Service;

use App\Administration\Application\Port\ActiveRoleStore;
use App\Administration\Domain\Model\User\Role;
use App\Administration\Domain\Model\User\User;

use function is_string;

use Psr\Cache\CacheItemPoolInterface;

use function sprintf;

use Symfony\Component\HttpFoundation\RequestStack;

final readonly class CacheActiveRoleStore implements ActiveRoleStore
{
    private const string CACHE_KEY_PREFIX = 'active_role_';
    private const int TTL_SECONDS = 604_800; // 7 jours

    public function __construct(
        private CacheItemPoolInterface $sessionsCache,
        private RequestStack $requestStack,
    ) {
    }

    public function store(User $user, Role $role): void
    {
        $item = $this->sessionsCache->getItem($this->cacheKey($user));
        $item->set($role->value);
        $item->expiresAfter(self::TTL_SECONDS);
        $this->sessionsCache->save($item);
    }

    public function get(User $user): ?Role
    {
        $item = $this->sessionsCache->getItem($this->cacheKey($user));

        if (!$item->isHit()) {
            return null;
        }

        $stored = $item->get();
        if (!is_string($stored)) {
            return null;
        }

        $role = Role::tryFrom($stored);
        if ($role !== null && $user->aLeRole($role)) {
            return $role;
        }

        return null;
    }

    public function clear(User $user): void
    {
        $this->sessionsCache->deleteItem($this->cacheKey($user));
    }

    private function cacheKey(User $user): string
    {
        $sessionId = $this->requestStack->getCurrentRequest()?->cookies->get('classeo_sid', '') ?? '';

        return sprintf('%s%s:%s', self::CACHE_KEY_PREFIX, $user->id, $sessionId);
    }
}
