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

use Chill\CustomFieldsBundle\EntityRepository\CustomFieldsDefaultGroupRepository;
use Chill\PersonBundle\Actions\PersonEdit\Service\PersonEditDTOFactory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Form\PersonType;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\TranslatableMessage;
use Twig\Environment;

final readonly class PersonEditController
{
    public function __construct(
        private Security $security,
        private FormFactoryInterface $formFactory,
        private CustomFieldsDefaultGroupRepository $customFieldsDefaultGroupRepository,
        private EntityManagerInterface $entityManager,
        private UrlGeneratorInterface $urlGenerator,
        private Environment $twig,
        private PersonEditDTOFactory $personEditDTOFactory,
    ) {}

    /**
     * @ParamConverter("person", options={"id": "person_id"})
     */
    #[Route(path: '/{_locale}/person/{person_id}/general/edit', name: 'chill_person_general_edit')]
    public function editAction(Person $person, Request $request, Session $session)
    {
        if (!$this->security->isGranted(PersonVoter::UPDATE, $person)) {
            throw new AccessDeniedHttpException('You are not allowed to edit this person.');
        }

        $dto = $this->personEditDTOFactory->createPersonEditDTO($person);

        $form = $this->formFactory->create(
            PersonType::class,
            $dto,
            ['cFGroup' => $this->customFieldsDefaultGroupRepository->findOneByEntity(Person::class)?->getCustomFieldsGroup()]
        );

        $form->handleRequest($request);

        if ($form->isSubmitted() && !$form->isValid()) {
            $session
                ->getFlashBag()->add('error', new TranslatableMessage('This form contains errors'));
        } elseif ($form->isSubmitted() && $form->isValid()) {
            $this->personEditDTOFactory->mapPersonEditDTOtoPerson($dto, $person);
            $this->entityManager->flush();

            $session->getFlashBag()->add('success', new TranslatableMessage('The person data has been updated'));

            return new RedirectResponse(
                $this->urlGenerator->generate('chill_person_view', ['person_id' => $person->getId()])
            );
        }

        return new Response($this->twig->render('@ChillPerson/Person/edit.html.twig', [
            'form' => $form->createView(),
            'person' => $person,
        ]));
    }
}
