<?php

declare(strict_types=1);

namespace Ferienpass\AdminBundle\Tests\Form\Filter;

use Doctrine\ORM\QueryBuilder;
use Ferienpass\AdminBundle\Form\Filter\Offer\HidePastFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\OnlineApplicationFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\RequiresApplicationFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\StatusFilter;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final class OfferFilterTypesTest extends TestCase
{
    // ---- HidePastFilter ----

    public function testHidePastFilterGetParent(): void
    {
        self::assertSame(CheckboxType::class, (new HidePastFilter())->getParent());
    }

    public function testHidePastFilterApplyDoesNothingWhenEmpty(): void
    {
        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);

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

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

    public function testHidePastFilterApplyDoesNothingWhenFalse(): void
    {
        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(false);
        $form->method('getData')->willReturn(false);

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

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

    // ---- OnlineApplicationFilter ----

    public function testOnlineApplicationFilterGetParent(): void
    {
        $security = $this->createMock(Security::class);
        self::assertSame(ChoiceType::class, (new OnlineApplicationFilter($security))->getParent());
    }

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

        self::assertTrue((new OnlineApplicationFilter($security))->shallDisplay());
    }

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

        self::assertFalse((new OnlineApplicationFilter($security))->shallDisplay());
    }

    public function testOnlineApplicationFilterApplyDoesNothingWhenEmpty(): void
    {
        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);

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

        $security = $this->createMock(Security::class);
        (new OnlineApplicationFilter($security))->apply($qb, $form);
    }

    // ---- StatusFilter ----

    public function testStatusFilterGetParent(): void
    {
        $translator = $this->createMock(TranslatorInterface::class);
        self::assertSame(ChoiceType::class, (new StatusFilter($translator))->getParent());
    }

    public function testStatusFilterApplyDoesNothingWhenEmpty(): void
    {
        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);

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

        $translator = $this->createMock(TranslatorInterface::class);
        (new StatusFilter($translator))->apply($qb, $form);
    }

    // ---- RequiresApplicationFilter ----

    public function testRequiresApplicationFilterGetParent(): void
    {
        $security = $this->createMock(Security::class);
        self::assertSame(ChoiceType::class, (new RequiresApplicationFilter($security))->getParent());
    }

    public function testRequiresApplicationFilterApplyDoesNothingWhenEmpty(): void
    {
        $form = $this->createMock(FormInterface::class);
        $form->method('isEmpty')->willReturn(true);

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

        $security = $this->createMock(Security::class);
        (new RequiresApplicationFilter($security))->apply($qb, $form);
    }
}
