<?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\TicketBundle\Tests\Controller;

use Chill\TicketBundle\Action\Ticket\ChangeEmergencyStateCommand;
use Chill\TicketBundle\Action\Ticket\Handler\ChangeEmergencyStateCommandHandler;
use Chill\TicketBundle\Controller\ChangeEmergencyStateApiController;
use Chill\TicketBundle\Entity\EmergencyStatusEnum;
use Chill\TicketBundle\Entity\Ticket;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\SerializerInterface;

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

    public function testSetEmergencyYesWithoutPermission(): void
    {
        $ticket = new Ticket();
        $security = $this->prophesize(Security::class);
        $security->isGranted('ROLE_USER')->willReturn(false);

        $changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class);
        $entityManager = $this->prophesize(EntityManagerInterface::class);
        $serializer = $this->prophesize(SerializerInterface::class);

        $controller = new ChangeEmergencyStateApiController(
            $changeEmergencyStateCommandHandler->reveal(),
            $security->reveal(),
            $entityManager->reveal(),
            $serializer->reveal(),
        );

        $this->expectException(AccessDeniedHttpException::class);
        $controller->setEmergencyYes($ticket);
    }

    public function testSetEmergencyYesWithPermission(): void
    {
        $ticket = new Ticket();

        $security = $this->prophesize(Security::class);
        $security->isGranted('ROLE_USER')->willReturn(true);

        $changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class);
        $changeEmergencyStateCommandHandler->__invoke(
            $ticket,
            Argument::that(fn (ChangeEmergencyStateCommand $command) => EmergencyStatusEnum::YES === $command->newEmergencyStatus)
        )->willReturn($ticket)->shouldBeCalled();

        $entityManager = $this->prophesize(EntityManagerInterface::class);
        $entityManager->flush()->shouldBeCalled();

        $serializer = $this->prophesize(SerializerInterface::class);
        $serializer->serialize($ticket, 'json', ['groups' => ['read']])
            ->willReturn('{}')
            ->shouldBeCalled();

        $controller = new ChangeEmergencyStateApiController(
            $changeEmergencyStateCommandHandler->reveal(),
            $security->reveal(),
            $entityManager->reveal(),
            $serializer->reveal(),
        );

        $response = $controller->setEmergencyYes($ticket);

        $this->assertInstanceOf(JsonResponse::class, $response);
    }

    public function testSetEmergencyNoWithoutPermission(): void
    {
        $ticket = new Ticket();
        $security = $this->prophesize(Security::class);
        $security->isGranted('ROLE_USER')->willReturn(false);

        $changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class);
        $entityManager = $this->prophesize(EntityManagerInterface::class);
        $serializer = $this->prophesize(SerializerInterface::class);

        $controller = new ChangeEmergencyStateApiController(
            $changeEmergencyStateCommandHandler->reveal(),
            $security->reveal(),
            $entityManager->reveal(),
            $serializer->reveal(),
        );

        $this->expectException(AccessDeniedHttpException::class);
        $controller->setEmergencyNo($ticket);
    }

    public function testSetEmergencyNoWithPermission(): void
    {
        $ticket = new Ticket();

        $security = $this->prophesize(Security::class);
        $security->isGranted('ROLE_USER')->willReturn(true);

        $changeEmergencyStateCommandHandler = $this->prophesize(ChangeEmergencyStateCommandHandler::class);
        $changeEmergencyStateCommandHandler->__invoke(
            $ticket,
            Argument::that(fn (ChangeEmergencyStateCommand $command) => EmergencyStatusEnum::NO === $command->newEmergencyStatus)
        )->willReturn($ticket)->shouldBeCalled();

        $entityManager = $this->prophesize(EntityManagerInterface::class);
        $entityManager->flush()->shouldBeCalled();

        $serializer = $this->prophesize(SerializerInterface::class);
        $serializer->serialize($ticket, 'json', ['groups' => ['read']])
            ->willReturn('{}')
            ->shouldBeCalled();

        $controller = new ChangeEmergencyStateApiController(
            $changeEmergencyStateCommandHandler->reveal(),
            $security->reveal(),
            $entityManager->reveal(),
            $serializer->reveal(),
        );

        $response = $controller->setEmergencyNo($ticket);

        $this->assertInstanceOf(JsonResponse::class, $response);
    }
}
