<?php declare(strict_types=1);

namespace Newland\Toubiz\Events\Neos\Tests\Unit\LinkHandler;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Neos\Flow\Tests\FunctionalTestCase;
use Neos\Neos\Domain\Model\Site;
use Newland\NeosCommon\Service\ControllerContextFactory;
use Newland\NeosTestingHelpers\InteractsWithNodes;
use Newland\Toubiz\Events\Neos\LinkHandler\EventLinkHandler;
use Newland\Toubiz\Events\Neos\LinkHandler\EventRecord;
use Newland\Toubiz\Events\Neos\Service\EventUrlService;
use Newland\Toubiz\Sync\Neos\Domain\Repository\EventRepository;
use Newland\Toubiz\Sync\Neos\Tests\Factory\EventFactory;

class EventLinkHandlerTest extends FunctionalTestCase
{
    protected static $testablePersistenceEnabled = true;
    use InteractsWithNodes;

    /** @var EventLinkHandler */
    protected $subject;

    /** @var EventFactory */
    protected $factory;

    /** @var Site */
    protected $site;

    /** @var Node */
    protected $node;

    /** @var ControllerContext */
    protected $controllerContext;

    /** @var EventUrlService */
    protected $eventUrlService;

    public function setUp(): void
    {
        parent::setUp();

        $this->site = $this->initializeSite('foo-bar');
        $this->node = $this->initializeNode('/sites/foo-bar', 'live', $this->site);
        $this->controllerContext =
            $this->objectManager->get(ControllerContextFactory::class)->initializeFakeControllerContext($this->node);

        $this->subject = $this->objectManager->get(EventLinkHandler::class);
        $this->eventUrlService = $this->objectManager->get(EventUrlService::class);
        $this->factory = new EventFactory($this->objectManager);
    }

    public function testFetchesEventsFromRepositoryWhenFindingLinkByIdentifier(): void
    {
        $event = $this->factory->create([ 'title' => 'This is a test' ]);
        $record = $this->subject->findByIdentifier($event->getPersistenceObjectIdentifier());

        $this->assertInstanceOf(EventRecord::class, $record);
        $this->assertEquals($event->getPersistenceObjectIdentifier(), $record->getId());
        $this->assertEquals(
            $event->getPersistenceObjectIdentifier(),
            $record->getEvent()->getPersistenceObjectIdentifier()
        );
    }

    public function testSearchesEventBySearchTerm(): void
    {
        $event = $this->factory->create([ 'title' => 'This is a test' ]);
        $results = $this->subject->findBySearchTerm('This');

        $this->assertEquals(1, count($results));
        $this->assertEquals($event->getPersistenceObjectIdentifier(), $results[0]->getId());
    }

    public function testGeneratesLinkForEventWithoutConfiguredOverride(): void
    {
        $event = $this->factory->create([ 'title' => 'This is a test', 'mainType' => 2 ]);
        $record = $this->subject->findByIdentifier($event->getPersistenceObjectIdentifier());

        $this->inject($this->eventUrlService, 'configuration', []);
        $link = $this->subject->generateRecordLink($record, $this->controllerContext, $this->node, false);
        $this->assertContains('/veranstaltung/this-is-a-test-', $link);
    }

    public function testGeneratesLinkForEventWithConfiguredOverride(): void
    {
        $event = $this->factory->create([ 'title' => 'This is a test', 'mainType' => 2 ]);
        $record = $this->subject->findByIdentifier($event->getPersistenceObjectIdentifier());

        $this->inject(
            $this->eventUrlService,
            'configuration',
            [
                'clients' =>
                    [
                        'Default' => [
                            'redirectToTportal' => true,
                            'detailUri' => 'http://test-url.com/event/detail/{name}-{id}',
                        ],
                    ],
            ]
        );
        $link = $this->subject->generateRecordLink($record, $this->controllerContext, $this->node, false);
        $this->assertEquals(
            'http://test-url.com/event/detail/this-is-a-test-' . $record->getEvent()->getOriginalId(),
            $link
        );

        $this->inject(
            $this->eventUrlService,
            'configuration',
            [
                'clients' =>
                    [
                        'Default' => [
                            'redirectToTportal' => false,
                            'detailUri' => 'http://test-url.com/event/detail/{name}-{id}',
                        ],
                    ],
            ]
        );
        $link = $this->subject->generateRecordLink($record, $this->controllerContext, $this->node, false);
        $this->assertContains('/veranstaltung/this-is-a-test-', $link);
    }

    public function testSettingLanguageDoesNotTaintRepository(): void
    {
        $repository = $this->objectManager->get(EventRepository::class);
        $repository->setLanguage('de');
        $german = $this->factory->create([ 'language' => 'de' ]);
        $english = $this->factory->create([ 'language' => 'en' ]);

        $this->subject->setLanguage('en');

        $ids = [];
        foreach ($repository->findAll() as $e) {
            $ids[] = $e->getPersistenceObjectIdentifier();
        }

        $this->assertContains($german->getPersistenceObjectIdentifier(), $ids, 'Should find german');
        $this->assertNotContains($english->getPersistenceObjectIdentifier(), $ids, 'Should not find english');
    }

    public function testGeneratingLinkDoesNotTaintRepository(): void
    {
        $repository = $this->objectManager->get(EventRepository::class);
        $repository->setLanguage('de');

        $event = $this->factory->create([ 'language' => 'en' ]);
        $this->subject->setLanguage('en');
        $record = $this->subject->findByIdentifier($event->getPersistenceObjectIdentifier());
        $link = $this->subject->generateRecordLink($record, $this->controllerContext, $this->node, false);

        $ids = [];
        foreach ($repository->findAll() as $e) {
            $ids[] = $e->getPersistenceObjectIdentifier();
        }

        $this->assertNotContains($event->getPersistenceObjectIdentifier(), $ids, 'Should not find english event');
    }

}
