<?php

namespace App\Tests\Unit\Service\Doctrine;

use App\Filter\Doctrine\TimeConstraint\ActivityYearFilter;
use App\Filter\Doctrine\TimeConstraint\DatetimeFilter;
use App\Service\Constraint\ActivityYearConstraint;
use App\Service\Constraint\DateTimeConstraint;
use App\Service\Doctrine\FiltersConfigurationService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\FilterCollection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class TestableFiltersConfigurationService extends FiltersConfigurationService {
    public function getFilters(): FilterCollection
    {
        return parent::getFilters();
    }
}


class FiltersConfigurationServiceTest extends TestCase
{
    private \PHPUnit\Framework\MockObject\MockObject|EntityManagerInterface $em;
    private DateTimeConstraint|\PHPUnit\Framework\MockObject\MockObject $dateTimeConstraint;
    private ActivityYearConstraint|\PHPUnit\Framework\MockObject\MockObject $activityYearConstraint;

    public function setUp(): void {
        $this->em = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
        $this->dateTimeConstraint = $this->getMockBuilder(DateTimeConstraint::class)->disableOriginalConstructor()->getMock();
        $this->activityYearConstraint = $this->getMockBuilder(ActivityYearConstraint::class)->disableOriginalConstructor()->getMock();
    }

    public function getSUTMockForMethod(string $methodName): MockObject | TestableFiltersConfigurationService {
        return $this
            ->getMockBuilder(TestableFiltersConfigurationService::class)
            ->setConstructorArgs([$this->em, $this->dateTimeConstraint, $this->activityYearConstraint])
            ->setMethodsExcept([$methodName])
            ->getMock();
    }

    public function testGetFilters(): void {
        $filterConfigurationService = $this->getSUTMockForMethod('getFilters');

        $filterCollection = $this->getMockBuilder(FilterCollection::class)->disableOriginalConstructor()->getMock();

        $this->em->expects(self::once())->method('getFilters')->willReturn($filterCollection);

        $this->assertEquals(
            $filterCollection,
            $filterConfigurationService->getFilters()
        );

    }

    public function testConfigureTimeConstraintFilters(): void {
        $filterConfigurationService = $this->getSUTMockForMethod('configureTimeConstraintFilters');

        $accessId = 123;

        $filterCollection = $this->getMockBuilder(FilterCollection::class)->disableOriginalConstructor()->getMock();

        $filterConfigurationService
            ->method('getFilters')
            ->willReturn($filterCollection);

        $datetimeFilter = $this->getMockBuilder(DatetimeFilter::class)->disableOriginalConstructor()->getMock();
        $activityYearFilter = $this->getMockBuilder(ActivityYearFilter::class)->disableOriginalConstructor()->getMock();

        $filterCollection
            ->expects(self::exactly(2))
            ->method('enable')
            ->willReturnMap([
                ['date_time_filter', $datetimeFilter],
                ['activity_year_filter', $activityYearFilter],
            ]);

        $datetimeFilter->expects(self::once())->method('setAccessId')->with($accessId);
        $datetimeFilter->expects(self::once())->method('setTimeConstraint')->with($this->dateTimeConstraint);

        $activityYearFilter->expects(self::once())->method('setAccessId')->with($accessId);
        $activityYearFilter->expects(self::once())->method('setTimeConstraint')->with($this->activityYearConstraint);

        $filterConfigurationService->configureTimeConstraintFilters($accessId);
    }

}
