<?php declare(strict_types=1);

namespace Newland\Toubiz\Sync\Neos\Tests\Unit\Domain\Filter;

use Neos\Flow\Tests\FunctionalTestCase;
use Newland\Toubiz\Sync\Neos\Domain\Filter\ArticleFilter;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Model\Attribute;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ArticleRepository;
use Newland\Toubiz\Sync\Neos\Tests\Factory\ArticleFactory;
use Newland\Toubiz\Sync\Neos\Tests\Factory\AttributeFactory;

class ArticleFilterTest extends FunctionalTestCase
{
    protected static $testablePersistenceEnabled = true;

    /** @var ArticleRepository */
    protected $repository;

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

    /** @var ArticleFactory */
    protected $attributeFactory;

    public function setUp(): void
    {
        parent::setUp();
        $this->factory = new ArticleFactory($this->objectManager);
        $this->attributeFactory = new AttributeFactory($this->objectManager);
        $this->repository = $this->objectManager->get(ArticleRepository::class);
        $this->repository->setLanguage('de');
    }

    /**
     * @dataProvider provideFilterConfigurations
     * @param array $filterAttributes
     */
    public function testAppliesLanguageFilter(array $filterAttributes): void
    {
        $german = $this->factory->create([
            'language' => 'de',
             'mainType' => 2,
             'attributes' => [
                 $this->attributeFactory->make([ 'name' => 'foo', 'data' => 'bar' ]),
                 $this->attributeFactory->make([ 'name' => 'foo', 'data' => 'baz' ]),
                 $this->attributeFactory->make([ 'name' => 'test', 'data' => 'here' ]),
             ],
         ]);
        $english = $this->factory->create([
             'language' => 'en',
             'mainType' => 2,
             'attributes' => [
                 $this->attributeFactory->make([ 'name' => 'foo', 'data' => 'bar' ]),
                 $this->attributeFactory->make([ 'name' => 'foo', 'data' => 'baz' ]),
                 $this->attributeFactory->make([ 'name' => 'test', 'data' => 'here' ]),
             ],
         ]);

        $filter = new ArticleFilter();
        foreach ($filterAttributes as $name => $content) {
            $filter->{'set' . ucfirst($name)}($content);
        }

        $ids = $this->idsForFilter($filter);
        $this->assertContains($german->getPersistenceObjectIdentifier(), $ids);
        $this->assertNotContains($english->getPersistenceObjectIdentifier(), $ids);
    }

    public function testFiltersForAttributes(): void
    {
        $attribute = new Attribute();
        $attribute->setName('foo');
        $attribute->setData('bar');
        $attribute->setIdentificationHash('foo-bar');
        $first = $this->factory->create([ 'language' => 'de', 'attributes' => [ $attribute ] ]);
        $second = $this->factory->create([ 'language' => 'de', 'attributes' => [ ] ]);

        $filter = new ArticleFilter();
        $filter->setAttributesIn([ 'foo' => [ 'bar' ] ]);
        $ids = $this->idsForFilter($filter);
        $this->assertContains($first->getPersistenceObjectIdentifier(), $ids);
        $this->assertNotContains($second->getPersistenceObjectIdentifier(), $ids);
    }

    public function provideFilterConfigurations(): array
    {
        return [
            'empty filter' => [ [] ],
            'empty zip array' => [ [
                'zips' => [ ]
            ] ],
            'filter for attributes' => [ [
                'attributesIn' => [
                    'foo' => [ 'bar' ]
                ]
            ] ],
            'filter for main type' => [ [
                'mainType' => 2
            ] ],
            'filter for main type and attributes' => [ [
                'mainType' => 2,
                'attributesIn' => [
                    'foo' => [ 'bar' ]
                ]
            ] ],
            'filter for main type and multiple attributes' => [ [
                'mainType' => 2,
                'attributesIn' => [
                    'foo' => [ 'bar', 'baz' ],
                    'test' => [ 'here' ]
                ]
            ] ],
        ];
    }

    private function idsForFilter(ArticleFilter $filter): array
    {
        $result = $this->repository->findByFilter($filter);
        return array_map(
            function(Article $article) {
                return $article->getPersistenceObjectIdentifier();
            },
            $result
        );
    }

}
