<?php declare(strict_types=1);

namespace Newland\Toubiz\Poi\Neos\Tests\Integration\FilteredTeaserList;

use Newland\Toubiz\Api\ObjectAdapter\Concern\ArticleConstants;
use Newland\Toubiz\Poi\Neos\Service\LinkListService;
use Newland\Toubiz\Poi\Neos\Tests\Integration\IntegrationTestCase;

abstract class FilteredTeaserListTestCase extends IntegrationTestCase
{
    protected abstract function articleType(): int;

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

        $this->node->setNodeType($this->nodeTypeManager->getNodeType('Newland.Toubiz.Poi.Neos:FilteredTeaserList'));
        $this->node->setProperty('articleType', $this->articleType());
        $this->persistNode($this->node);

        $service = $this->createMock(LinkListService::class);
        $service->method('getLinkTargetNodeByClientAndArticleType')->willReturn('');
        $this->objectManager->setInstance(LinkListService::class, $service);
    }

    public function tearDown(): void
    {
        $this->objectManager->forgetInstance(LinkListService::class);
        parent::tearDown();
    }

    public function testRendersArticles(): void
    {
        $this->articleFactory->create([ 'mainType' => $this->articleType(), 'name' => '__FIRST__' ]);
        $this->articleFactory->create([ 'mainType' => $this->articleType(), 'name' => '__SECOND__' ]);

        $response = $this->browser->request($this->nodeUri);
        $this->assertResponseOk($response);

        $this->assertResponseContains('__FIRST__', $response);
        $this->assertResponseContains('__SECOND__', $response);
    }

    /** @dataProvider provideOtherArticleTypes */
    public function testDoesNotShowArticlesOfDifferentType($type): void
    {
        $hash = md5(random_bytes(32));
        $correctName = sprintf('__CORRECT_%s__', $hash);
        $otherName = sprintf('__OTHER_TYPE_%s__', $hash);
        $this->articleFactory->create([ 'mainType' => $this->articleType(), 'name' => $correctName ]);
        $this->articleFactory->create([ 'mainType' => (int) $type, 'name' => $otherName ]);

        $response = $this->browser->request($this->nodeUri);
        $this->assertResponseOk($response);

        $this->assertResponseContains($correctName, $response);
        $this->assertResponseNotContains($otherName, $response);
    }

    public function provideOtherArticleTypes(): array
    {
        $otherTypes = array_filter(
            ArticleConstants::ALL_TYPES,
            function ($type) {
                return $type !== $this->articleType();
            }
        );

        return array_map(
            function ($type) {
                return [ $type ];
            },
            $otherTypes
        );
    }
}
