<?php declare(strict_types=1);

namespace Newland\NeosFiltering\Tests\Unit\Items;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Neos\FluidAdaptor\View\StandaloneView;
use Newland\Contracts\Neos\Filter\FilterItem;
use Newland\NeosFiltering\Tests\BaseTestCase;
use Newland\NeosFiltering\Tests\Fixture\Domain\Model\ExampleEntity;

abstract class ItemTestCase extends BaseTestCase
{
    /** @var EntityManagerInterface */
    protected $entityManager;

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

    public function setUp():  void
    {
        parent::setUp();
        $this->entityManager = $this->objectManager->get(EntityManagerInterface::class);
    }

    protected function renderSubject(): ?string
    {
        $view = new StandaloneView();
        $view->assign('subject', $this->subject);
        $view->setTemplateSource('<f:render renderable="{subject}" />');
        return $view->render();
    }

    protected function initializeEmptyQuery(): QueryBuilder
    {
        /** @var QueryBuilder $query */
        $query = $this->objectManager->get(EntityManagerInterface::class)->createQueryBuilder();
        $query->select('entity')->from(ExampleEntity::class, 'entity');
        $query->groupBy('entity');
        return $query;
    }


    protected function queryForSubject(): QueryBuilder
    {
        $query = $this->initializeEmptyQuery();
        $expression = $this->subject->queryExpression($query->expr());
        if ($expression->where) {
            $query->where($expression->where);
        }
        if ($expression->having) {
            $query->having($expression->having);
        }

        return $query;
    }

    protected function assertContainsCount(string $contains, int $count, string $haystack, ?string $message = null): void
    {
        $actual = substr_count($haystack, $contains);
        if (!$message) {
            $message = sprintf(
                'Failed asserting that "%s" contains "%s" exactly %d times: Actually contains it %d times',
                $haystack,
                $contains,
                $count,
                $actual
            );
        }
        $this->assertEquals($count, $actual, $message);
    }
}
