<?php

declare(strict_types=1);

namespace Ferienpass\AdminBundle\Tests\Form\Filter;

use Doctrine\ORM\QueryBuilder;
use Ferienpass\AdminBundle\Form\Filter\EditionFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\HostFilter;
use Ferienpass\CoreBundle\Repository\HostRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\FormInterface;

final class FilterDisplayTest extends TestCase
{
    // ---- HostFilter ----

    public function testHostFilterGetParent(): void
    {
        $security = $this->createMock(Security::class);
        $hosts = $this->createMock(HostRepository::class);

        self::assertSame(EntityType::class, (new HostFilter($security, $hosts))->getParent());
    }

    public function testHostFilterShallDisplayReturnsTrueForAdmin(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->with('ROLE_ADMIN')->willReturn(true);
        $hosts = $this->createMock(HostRepository::class);

        self::assertTrue((new HostFilter($security, $hosts))->shallDisplay());
    }

    public function testHostFilterShallDisplayReturnsFalseForNonAdmin(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->with('ROLE_ADMIN')->willReturn(false);
        $hosts = $this->createMock(HostRepository::class);

        self::assertFalse((new HostFilter($security, $hosts))->shallDisplay());
    }

    public function testHostFilterApplyDoesNothingWhenEmptyAndAdmin(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->with('ROLE_ADMIN')->willReturn(true);

        $hosts = $this->createMock(HostRepository::class);

        $parentConfig = $this->createMock(\Symfony\Component\Form\FormConfigInterface::class);
        $parentConfig->method('getOption')->with('view_id')->willReturn('admin_offers_index');
        $parentForm = $this->createMock(FormInterface::class);
        $parentForm->method('getConfig')->willReturn($parentConfig);

        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);
        $form->method('getParent')->willReturn($parentForm);

        $qb = $this->createMock(QueryBuilder::class);
        $qb->expects(self::never())->method('andWhere');
        $qb->expects(self::never())->method('where');

        (new HostFilter($security, $hosts))->apply($qb, $form);
    }

    // ---- EditionFilter ----

    public function testEditionFilterGetParent(): void
    {
        $security = $this->createMock(Security::class);

        self::assertSame(EntityType::class, (new EditionFilter($security))->getParent());
    }

    public function testEditionFilterShallDisplayReturnsTrueForNonOffersView(): void
    {
        $security = $this->createMock(Security::class);
        $security->expects(self::never())->method('isGranted');

        self::assertTrue((new EditionFilter($security))->shallDisplay('admin_attendances_index'));
    }

    public function testEditionFilterShallDisplayForOffersViewDependsOnRole(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->with('ROLE_ADMIN')->willReturn(true);

        self::assertTrue((new EditionFilter($security))->shallDisplay('admin_offers_index'));
    }

    public function testEditionFilterShallDisplayForOffersViewReturnsFalseForNonAdmin(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->with('ROLE_ADMIN')->willReturn(false);

        self::assertFalse((new EditionFilter($security))->shallDisplay('admin_offers_index'));
    }

    public function testEditionFilterApplyReturnsEarlyWhenEmpty(): void
    {
        $security = $this->createMock(Security::class);
        $security->method('isGranted')->willReturn(true);

        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);
        $form->method('getName')->willReturn('edition');

        $parentForm = $this->createMock(FormInterface::class);
        $parentConfig = $this->createMock(\Symfony\Component\Form\FormConfigInterface::class);
        $parentConfig->method('getOption')->with('view_id')->willReturn('admin_attendances_index');
        $parentForm->method('getConfig')->willReturn($parentConfig);
        $form->method('getParent')->willReturn($parentForm);

        $qb = $this->createMock(QueryBuilder::class);
        $qb->expects(self::never())->method('andWhere');

        (new EditionFilter($security))->apply($qb, $form);
    }
}
