<?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\EventSubscriber;

use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\EventSubscriber\NotificationOnTransition;
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\Event;
use Symfony\Component\Workflow\Marking;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\WorkflowInterface;

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

    public function testOnCompleteSendNotification(): void
    {
        $dest = new User();
        $currentUser = new User();
        $workflowProphecy = $this->prophesize(WorkflowInterface::class);
        $workflow = $workflowProphecy->reveal();
        $entityWorkflow = new EntityWorkflow();
        $entityWorkflow
            ->setWorkflowName('workflow_name')
            ->setRelatedEntityClass(\stdClass::class)
            ->setRelatedEntityId(1);
        // force an id to entityWorkflow:
        $reflection = new \ReflectionClass($entityWorkflow);
        $id = $reflection->getProperty('id');
        $id->setAccessible(true);
        $id->setValue($entityWorkflow, 1);

        $step = new EntityWorkflowStep();
        $userGroup = (new UserGroup())->addUser($userInGroup = new User())->addUser($dest);
        $entityWorkflow->addStep($step);
        $step
            ->addDestUser($dest)
            ->addDestUserGroup($userGroup)
            ->setCurrentStep('to_state');

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

        // we check that both notification has been persisted once,
        // eliminating doublons
        $em->persist(Argument::that(
            fn ($notificationCandidate) => $notificationCandidate instanceof Notification && $notificationCandidate->getAddressees()->contains($dest)
        ))->shouldBeCalledOnce();
        $em->persist(Argument::that(
            fn ($notificationCandidate) => $notificationCandidate instanceof Notification && $notificationCandidate->getAddressees()->contains($userInGroup)
        ))->shouldBeCalledOnce();

        $engine = $this->prophesize(\Twig\Environment::class);
        $engine->render(Argument::type('string'), Argument::type('array'))
            ->willReturn('dummy text');

        $extractor = $this->prophesize(MetadataExtractor::class);
        $extractor->buildArrayPresentationForPlace(Argument::type(EntityWorkflow::class), Argument::any())
            ->willReturn([]);
        $extractor->buildArrayPresentationForWorkflow(Argument::any())
            ->willReturn([]);

        $registry = $this->prophesize(Registry::class);
        $registry->get(Argument::type(EntityWorkflow::class), Argument::type('string'))
            ->willReturn($workflow);

        $security = $this->prophesize(Security::class);
        $security->getUser()->willReturn($currentUser);

        $entityWorkflowHandler = $this->prophesize(EntityWorkflowHandlerInterface::class);
        $entityWorkflowHandler->getEntityTitle($entityWorkflow)->willReturn('workflow title');
        $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
        $entityWorkflowManager->getHandler($entityWorkflow)->willReturn($entityWorkflowHandler->reveal());

        $notificationOnTransition = new NotificationOnTransition(
            $em->reveal(),
            $engine->reveal(),
            $extractor->reveal(),
            $security->reveal(),
            $registry->reveal(),
            $entityWorkflowManager->reveal(),
        );

        $event = new Event($entityWorkflow, new Marking(), new Transition('dummy_transition', ['from_state'], ['to_state']), $workflow);

        $notificationOnTransition->onCompletedSendNotification($event);
    }
}
