<?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 Chill\MainBundle\Tests\Workflow\Messenger;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\Messenger\PostSendExternalMessage;
use Chill\MainBundle\Workflow\Messenger\PostSendExternalMessageHandler;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;

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

    public function testSendMessageHappyScenario(): void
    {
        $entityWorkflow = $this->buildEntityWorkflow();
        $dto = new WorkflowTransitionContextDTO($entityWorkflow);
        $dto->futureDestineeEmails = ['external@example.com'];
        $dto->futureDestineeThirdParties = [(new ThirdParty())->setEmail('3party@example.com')];
        $entityWorkflow->setStep('send_external', $dto, 'to_send_external', new \DateTimeImmutable(), new User());

        $repository = $this->prophesize(EntityWorkflowRepository::class);
        $repository->find(1)->willReturn($entityWorkflow);

        $mailer = $this->prophesize(MailerInterface::class);
        $mailer->send(Argument::that($this->buildCheckAddressCallback('3party@example.com')))->shouldBeCalledOnce();
        $mailer->send(Argument::that($this->buildCheckAddressCallback('external@example.com')))->shouldBeCalledOnce();

        $workflowHandler = $this->prophesize(EntityWorkflowHandlerInterface::class);
        $workflowHandler->getEntityTitle($entityWorkflow, Argument::any())->willReturn('title');
        $workflowManager = $this->prophesize(EntityWorkflowManager::class);
        $workflowManager->getHandler($entityWorkflow)->willReturn($workflowHandler->reveal());

        $handler = new PostSendExternalMessageHandler($repository->reveal(), $mailer->reveal(), $workflowManager->reveal());

        $handler(new PostSendExternalMessage(1, 'fr'));

        // prophecy should do the check at the end of this test
    }

    private function buildCheckAddressCallback(string $emailToCheck): callable
    {
        return fn (TemplatedEmail $email): bool => in_array($emailToCheck, array_map(fn (Address $addr) => $addr->getAddress(), $email->getTo()), true);
    }

    private function buildEntityWorkflow(): EntityWorkflow
    {
        $entityWorkflow = new EntityWorkflow();
        $reflection = new \ReflectionClass($entityWorkflow);
        $idProperty = $reflection->getProperty('id');
        $idProperty->setValue($entityWorkflow, 1);

        return $entityWorkflow;
    }
}
