<?php

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 Notification\Email;

use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\NotificationComment;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Notification\Email\NotificationMailer;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\PostPersistEventArgs;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Log\NullLogger;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Translation\Translator;

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

    public function testPostPersistComment(): void
    {
        $user1 = (new User())->setEmail('user1@foo.com');
        $user2 = (new User())->setEmail('user2@foo.com');
        $user3 = (new User())->setEmail('user3@foo.com');

        $notification = new Notification();
        $notification
            ->setTitle('test notification')
            ->setSender($user1)
            ->addAddressee($user2)
            ->addAddressee($user3)
        ;

        $comment = (new NotificationComment())
            ->setContent('foo bar baz')
            ->setCreatedBy($user2)
        ;
        $notification->addComment($comment);

        $mailer = $this->prophesize(MailerInterface::class);

        // a mail only to user1 and user3 should have been sent
        $mailer->send(Argument::that(function (Email $email) {
            foreach ($email->getTo() as $address) {
                if ('user1@foo.com' === $address->getAddress() || 'user3@foo.com' === $address->getAddress()) {
                    return true;
                }
            }

            return false;
        }))->shouldBeCalledTimes(2);

        $objectManager = $this->prophesize(EntityManagerInterface::class);

        $mailer = $this->buildNotificationMailer($mailer->reveal());
        $mailer->postPersistComment($comment, new PostPersistEventArgs($comment, $objectManager->reveal()));
    }

    public function testPostPersistCommentDestWithNullEmail(): void
    {
        $user1 = (new User())->setEmail('user1@foo.com');
        $user2 = (new User())->setEmail('user2@foo.com');
        $user3 = (new User())->setEmail(null);

        $notification = new Notification();
        $notification
            ->setTitle('test notification')
            ->setSender($user1)
            ->addAddressee($user2)
            ->addAddressee($user3)
        ;

        $comment = (new NotificationComment())
            ->setContent('foo bar baz')
            ->setCreatedBy($user2)
        ;
        $notification->addComment($comment);

        $mailer = $this->prophesize(MailerInterface::class);

        // a mail only to user1 and user3 should have been sent
        $mailer->send(Argument::that(function (Email $email) {
            foreach ($email->getTo() as $address) {
                if ('user1@foo.com' === $address->getAddress()) {
                    return true;
                }
            }

            return false;
        }))->shouldBeCalledTimes(1);

        $objectManager = $this->prophesize(EntityManagerInterface::class);

        $mailer = $this->buildNotificationMailer($mailer->reveal());
        $mailer->postPersistComment($comment, new PostPersistEventArgs($comment, $objectManager->reveal()));
    }

    private function buildNotificationMailer(
        ?MailerInterface $mailer = null,
    ): NotificationMailer {
        return new NotificationMailer(
            $mailer,
            new NullLogger(),
            new Translator('fr')
        );
    }
}
