<?php

/**
 * Chill is a software for social workers.
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\CalendarBundle\Tests\Service\ShortMessageNotification;

use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Repository\CalendarRepository;
use Chill\CalendarBundle\Service\ShortMessageNotification\CalendarForShortMessageProvider;
use Chill\CalendarBundle\Service\ShortMessageNotification\RangeGeneratorInterface;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;

/**
 * @internal
 *
 * @coversNothing
 */
final class CalendarForShortMessageProviderTest extends TestCase
{
    use ProphecyTrait;

    public function testGenerateRangeIsNull()
    {
        $calendarRepository = $this->prophesize(CalendarRepository::class);
        $calendarRepository->findByNotificationAvailable(
            Argument::type(\DateTimeImmutable::class),
            Argument::type(\DateTimeImmutable::class),
            Argument::type('int'),
            Argument::exact(0)
        )->shouldBeCalledTimes(0);
        $rangeGenerator = $this->prophesize(RangeGeneratorInterface::class);
        $rangeGenerator->generateRange(Argument::type(\DateTimeImmutable::class))->willReturn(null);

        $em = $this->prophesize(EntityManagerInterface::class);
        $em->clear()->shouldNotBeCalled();

        $provider = new CalendarForShortMessageProvider(
            $calendarRepository->reveal(),
            $em->reveal(),
            $rangeGenerator->reveal()
        );

        $calendars = iterator_to_array($provider->getCalendars(new \DateTimeImmutable('now')));

        $this->assertEquals(0, \count($calendars));
    }

    public function testGetCalendars()
    {
        $calendarRepository = $this->prophesize(CalendarRepository::class);
        $calendarRepository->findByNotificationAvailable(
            Argument::type(\DateTimeImmutable::class),
            Argument::type(\DateTimeImmutable::class),
            Argument::type('int'),
            Argument::exact(0)
        )->will(static fn ($args) => array_fill(0, $args[2], new Calendar()))->shouldBeCalledTimes(1);
        $calendarRepository->findByNotificationAvailable(
            Argument::type(\DateTimeImmutable::class),
            Argument::type(\DateTimeImmutable::class),
            Argument::type('int'),
            Argument::not(0)
        )->will(static fn ($args) => array_fill(0, $args[2] - 1, new Calendar()))->shouldBeCalledTimes(1);

        $em = $this->prophesize(EntityManagerInterface::class);
        $em->clear()->shouldBeCalled();

        $calendarRangeGenerator = $this->prophesize(RangeGeneratorInterface::class);
        $calendarRangeGenerator->generateRange(Argument::any())->willReturn([
            'startDate' => new \DateTimeImmutable('yesterday'),
            'endDate' => new \DateTimeImmutable('now'),
        ]);

        $provider = new CalendarForShortMessageProvider(
            $calendarRepository->reveal(),
            $em->reveal(),
            $calendarRangeGenerator->reveal(),
        );

        $calendars = iterator_to_array($provider->getCalendars(new \DateTimeImmutable('now')));

        $this->assertGreaterThan(1, \count($calendars));
        $this->assertLessThan(100, \count($calendars));
        $this->assertContainsOnly(Calendar::class, $calendars);
    }

    public function testGetCalendarsWithOnlyOneCalendar()
    {
        $calendarRepository = $this->prophesize(CalendarRepository::class);
        $calendarRepository->findByNotificationAvailable(
            Argument::type(\DateTimeImmutable::class),
            Argument::type(\DateTimeImmutable::class),
            Argument::type('int'),
            Argument::exact(0)
        )->will(static fn ($args) => array_fill(0, 10, new Calendar()))->shouldBeCalledTimes(1);
        $calendarRepository->findByNotificationAvailable(
            Argument::type(\DateTimeImmutable::class),
            Argument::type(\DateTimeImmutable::class),
            Argument::type('int'),
            Argument::exact(10)
        )->will(static fn ($args) => [])->shouldBeCalledTimes(1);

        $em = $this->prophesize(EntityManagerInterface::class);
        $em->clear()->shouldBeCalled();

        $calendarRangeGenerator = $this->prophesize(RangeGeneratorInterface::class);
        $calendarRangeGenerator->generateRange(Argument::any())->willReturn([
            'startDate' => new \DateTimeImmutable('yesterday'),
            'endDate' => new \DateTimeImmutable('now'),
        ]);

        $provider = new CalendarForShortMessageProvider(
            $calendarRepository->reveal(),
            $em->reveal(),
            $calendarRangeGenerator->reveal(),
        );

        $calendars = iterator_to_array($provider->getCalendars(new \DateTimeImmutable('now')));

        $this->assertEquals(10, \count($calendars));
        $this->assertContainsOnly(Calendar::class, $calendars);
    }
}
