<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Tests\EventListener\HttpCache;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Doctrine\ORM\Event\PostRemoveEventArgs;
use Doctrine\ORM\Event\PostUpdateEventArgs;
use Ferienpass\CoreBundle\Entity\Notification;
use Ferienpass\CoreBundle\EventListener\HttpCache\CacheInvalidationListener;
use FOS\HttpCacheBundle\CacheManager;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouterInterface;

/**
 * The notification preview pages are parameterised by type/edition, so they need
 * a host-scoped regex BAN (an exact-URL PURGE would miss them). Editing one type
 * must not evict the others; creating/deleting must, because the left-nav status
 * dot for the type changes on every page.
 */
final class CacheInvalidationListenerNotificationTest extends TestCase
{
    public function testEditingANotificationBansOnlyThatTypesPages(): void
    {
        $cacheManager = $this->createMock(CacheManager::class);
        $cacheManager->expects(self::once())
            ->method('invalidateRegex')
            ->with('^(/[a-z]{2,3})?/admin/benachrichtigungen/attendance_withdrawn(/|\?|$)', self::anything(), ['example.com']);

        $listener = new CacheInvalidationListener($cacheManager, $this->router(), 'test-app');

        $listener->postUpdate(new PostUpdateEventArgs(
            new Notification('attendance_withdrawn'),
            $this->createMock(EntityManagerInterface::class),
        ));
    }

    public function testCreatingANotificationBansTheWholeArea(): void
    {
        $cacheManager = $this->createMock(CacheManager::class);
        $cacheManager->expects(self::once())
            ->method('invalidateRegex')
            ->with('^(/[a-z]{2,3})?/admin/benachrichtigungen(/|\?|$)', self::anything(), ['example.com']);

        $listener = new CacheInvalidationListener($cacheManager, $this->router(), 'test-app');

        $listener->postPersist(new PostPersistEventArgs(
            new Notification('attendance_withdrawn'),
            $this->createMock(EntityManagerInterface::class),
        ));
    }

    public function testDeletingANotificationBansTheWholeArea(): void
    {
        $cacheManager = $this->createMock(CacheManager::class);
        $cacheManager->expects(self::once())
            ->method('invalidateRegex')
            ->with('^(/[a-z]{2,3})?/admin/benachrichtigungen(/|\?|$)', self::anything(), ['example.com']);

        $listener = new CacheInvalidationListener($cacheManager, $this->router(), 'test-app');

        $listener->postRemove(new PostRemoveEventArgs(
            new Notification('attendance_withdrawn'),
            $this->createMock(EntityManagerInterface::class),
        ));
    }

    private function router(): RouterInterface
    {
        $router = $this->createMock(RouterInterface::class);
        $router->method('getContext')->willReturn(new RequestContext('', 'GET', 'example.com', 'https'));

        return $router;
    }
}
