<?php

declare(strict_types=1);

namespace Ferienpass\AdminBundle\Tests\Form\Filter;

use Doctrine\ORM\QueryBuilder;
use Ferienpass\AdminBundle\Form\Filter\Consent\StatusFilter as ConsentStatusFilter;
use Ferienpass\AdminBundle\Form\Filter\Consent\TypeFilter as ConsentTypeFilter;
use Ferienpass\AdminBundle\Form\Filter\Debtor\WithBalanceFilter;
use Ferienpass\AdminBundle\Form\Filter\Debtor\WithDueSumFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\AttendancesWaitingFilter;
use Ferienpass\AdminBundle\Form\Filter\Offer\RequiresAgreementLetterFilter;
use Symfony\Bundle\SecurityBundle\Security;
use Ferienpass\AdminBundle\Form\Filter\Participant\UnpaidFilter as ParticipantUnpaidFilter;
use Ferienpass\AdminBundle\Form\Filter\Payment\StatusFilter as PaymentStatusFilter;
use Ferienpass\AdminBundle\Form\Filter\Payment\UserFilter as PaymentUserFilter;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
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 MoreFilterTypesTest extends TestCase
{
    // ---- ConsentStatusFilter ----

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

    public function testConsentStatusFilterApplyDoesNothingWhenEmpty(): 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 ConsentStatusFilter($translator))->apply($qb, $form);
    }

    // ---- ConsentTypeFilter ----

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

    public function testConsentTypeFilterApplyDoesNothingWhenEmpty(): 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 ConsentTypeFilter($translator))->apply($qb, $form);
    }

    // ---- WithBalanceFilter ----

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

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

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

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

    // ---- WithDueSumFilter ----

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

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

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

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

    // ---- PaymentStatusFilter ----

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

    public function testPaymentStatusFilterApplyDoesNothingWhenEmpty(): 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 PaymentStatusFilter($translator))->apply($qb, $form);
    }

    // ---- PaymentUserFilter ----

    public function testPaymentUserFilterGetParent(): void
    {
        self::assertSame(EntityType::class, (new PaymentUserFilter())->getParent());
    }

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

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

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

    // ---- AttendancesWaitingFilter ----

    public function testAttendancesWaitingFilterGetParent(): void
    {
        $security = $this->createMock(Security::class);
        self::assertSame(CheckboxType::class, (new AttendancesWaitingFilter($security))->getParent());
    }

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

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

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

    // ---- RequiresAgreementLetterFilter ----

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

    public function testRequiresAgreementLetterFilterApplyDoesNothingWhenEmpty(): 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 RequiresAgreementLetterFilter($security))->apply($qb, $form);
    }

    // ---- ParticipantUnpaidFilter ----

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

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

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

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