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

use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowAttachment;
use Chill\MainBundle\Security\Authorization\EntityWorkflowVoter;
use Chill\MainBundle\Workflow\Attachment\AddAttachmentAction;
use Chill\MainBundle\Workflow\Attachment\AddAttachmentRequestDTO;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class WorkflowAttachmentController
{
    public function __construct(
        private readonly Security $security,
        private readonly SerializerInterface $serializer,
        private readonly ValidatorInterface $validator,
        private readonly EntityManagerInterface $entityManager,
        private readonly AddAttachmentAction $addAttachmentAction,
    ) {}

    #[Route('/api/1.0/main/workflow/{id}/attachment', methods: ['POST'])]
    public function addAttachment(EntityWorkflow $entityWorkflow, Request $request): JsonResponse
    {
        if (!$this->security->isGranted(EntityWorkflowVoter::SEE, $entityWorkflow)) {
            throw new AccessDeniedHttpException();
        }

        $dto = new AddAttachmentRequestDTO($entityWorkflow);
        $this->serializer->deserialize($request->getContent(), AddAttachmentRequestDTO::class, 'json', [
            AbstractNormalizer::OBJECT_TO_POPULATE => $dto, AbstractNormalizer::GROUPS => ['write'],
        ]);

        $errors = $this->validator->validate($dto);

        if (count($errors) > 0) {
            return new JsonResponse(
                $this->serializer->serialize($errors, 'json'),
                Response::HTTP_UNPROCESSABLE_ENTITY,
                json: true
            );
        }

        $attachment = ($this->addAttachmentAction)($dto);

        $this->entityManager->flush();

        return new JsonResponse(
            $this->serializer->serialize($attachment, 'json', [AbstractNormalizer::GROUPS => ['read']]),
            json: true
        );
    }

    #[Route('/api/1.0/main/workflow/attachment/{id}', methods: ['DELETE'])]
    public function removeAttachment(EntityWorkflowAttachment $attachment): Response
    {
        if (!$this->security->isGranted(EntityWorkflowVoter::SEE, $attachment->getEntityWorkflow())) {
            throw new AccessDeniedHttpException();
        }

        $this->entityManager->remove($attachment);
        $this->entityManager->flush();

        return new Response(null, Response::HTTP_NO_CONTENT);
    }

    #[Route('/api/1.0/main/workflow/{id}/attachment', methods: ['GET'])]
    public function listAttachmentsForEntityWorkflow(EntityWorkflow $entityWorkflow): JsonResponse
    {
        if (!$this->security->isGranted(EntityWorkflowVoter::SEE, $entityWorkflow)) {
            throw new AccessDeniedHttpException();
        }

        return new JsonResponse(
            $this->serializer->serialize(
                $entityWorkflow->getAttachments(),
                'json',
                [AbstractNormalizer::GROUPS => ['read']]
            ),
            json: true
        );
    }
}
