<?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\Service\ShortMessageNotification\BulkCalendarShortMessageSender;
use Chill\CalendarBundle\Service\ShortMessageNotification\CalendarForShortMessageProvider;
use Chill\CalendarBundle\Service\ShortMessageNotification\ShortMessageForCalendarBuilderInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\PersonBundle\DataFixtures\Helper\PersonRandomHelper;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Log\NullLogger;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Notifier\Message\SentMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\TexterInterface;

/**
 * @internal
 *
 * @coversNothing
 */
final class BulkCalendarShortMessageSenderTest extends KernelTestCase
{
    use PersonRandomHelper;

    use PrepareUserTrait;

    use ProphecyTrait;

    private array $toDelete = [];

    protected function setUp(): void
    {
        parent::setUp();
        self::bootKernel();
    }

    protected function tearDown(): void
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);

        foreach ($this->toDelete as [$entity, $id]) {
            $entity = $em->find($entity, $id);
            $em->remove($entity);
        }

        $em->flush();
    }

    public function testSendBulkMessageToEligibleCalendar()
    {
        $em = self::getContainer()->get(EntityManagerInterface::class);
        $calendar = new Calendar();
        $calendar
            ->addPerson($this->getRandomPerson($em))
            ->setMainUser($user = $this->prepareUser([]))
            ->setStartDate(new \DateTimeImmutable('now'))
            ->setEndDate($calendar->getStartDate()->add(new \DateInterval('PT30M')))
            ->setSendSMS(true);

        $user->setUsername(uniqid());
        $user->setEmail(uniqid().'@gmail.com');
        $calendar->getPersons()->first()->setAcceptSMS(true);

        // hack to prevent side effect with messages
        $calendar->preventEnqueueChanges = true;

        $em->persist($user);
        // $this->toDelete[] = [User::class, $user->getId()];
        $em->persist($calendar);
        // $this->toDelete[] = [Calendar::class, $calendar->getId()];
        $em->flush();

        $provider = $this->prophesize(CalendarForShortMessageProvider::class);
        $provider->getCalendars(Argument::type(\DateTimeImmutable::class))
            ->willReturn(new \ArrayIterator([$calendar]));

        $messageBuilder = $this->prophesize(ShortMessageForCalendarBuilderInterface::class);
        $messageBuilder->buildMessageForCalendar(Argument::type(Calendar::class))
            ->willReturn(
                [
                    new SmsMessage(
                        '+32470123456',
                        'content',
                    ),
                ]
            );

        $texter = $this->prophesize(TexterInterface::class);
        $texter->send(Argument::type(SmsMessage::class))
            ->will(fn ($args): SentMessage => new SentMessage($args[0], 'sms'))
            ->shouldBeCalledTimes(1);

        $bulk = new BulkCalendarShortMessageSender(
            $provider->reveal(),
            $em,
            new NullLogger(),
            $texter->reveal(),
            $messageBuilder->reveal()
        );

        $bulk->sendBulkMessageToEligibleCalendars();

        $em->clear();
        $calendar = $em->find(Calendar::class, $calendar->getId());

        $this->assertEquals(Calendar::SMS_SENT, $calendar->getSmsStatus());
    }
}
