<?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\Handler\ReplaceMotiveCommandHandler;
use Chill\TicketBundle\Action\Ticket\ReplaceMotiveCommand;
use Chill\TicketBundle\Entity\Motive;
use PHPUnit\Framework\TestCase;
use Chill\TicketBundle\Controller\ReplaceMotiveController;
use Chill\TicketBundle\Entity\Ticket;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validator\ValidatorInterface;

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

    private function buildController(Ticket $ticket, string $body, Motive $motive): ReplaceMotiveController
    {
        $command = new ReplaceMotiveCommand($motive);

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

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

        $replaceMotiveCommandHandler = $this->prophesize(ReplaceMotiveCommandHandler::class);
        $replaceMotiveCommandHandler->handle($ticket, $command)->shouldBeCalled();

        // Mock Validator
        $validator = $this->prophesize(ValidatorInterface::class);
        $validator->validate($command)
            ->shouldBeCalled()
            ->willReturn(new ConstraintViolationList([]));

        $serializer = $this->prophesize(SerializerInterface::class);
        $serializer->deserialize($body, ReplaceMotiveCommand::class, 'json', [AbstractNormalizer::GROUPS => ['write']])
            ->willReturn($command);
        $serializer->serialize($ticket, 'json', ['groups' => ['read']])
            ->shouldBeCalled()
            ->willReturn('{"type": "ticket", "id": 1}');

        return new ReplaceMotiveController(
            $security->reveal(),
            $replaceMotiveCommandHandler->reveal(),
            $serializer->reveal(),
            $validator->reveal(),
            $entityManager->reveal()
        );
    }

    public function testAddValidMotive(): void
    {
        $ticket = new Ticket();
        $motive = new Motive();

        $payload = <<<'JSON'
            {"motive": {"type":  "ticket_motive", "id": 1}}
            JSON;

        $request = new Request(content: $payload);

        $controller = $this->buildController($ticket, $payload, $motive);

        $response = $controller($ticket, $request);

        self::assertEquals(201, $response->getStatusCode());
    }
}
