<?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\MainBundle\Pagination\PaginatorFactory;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
use Chill\PersonBundle\Form\HouseholdCompositionType;
use Chill\PersonBundle\Repository\Household\HouseholdCompositionRepository;
use Chill\PersonBundle\Repository\Household\HouseholdRepository;
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

class HouseholdCompositionController extends AbstractController
{
    public function __construct(
        private readonly Security $security,
        private readonly HouseholdCompositionRepository $householdCompositionRepository,
        private readonly HouseholdRepository $householdRepository,
        private readonly PaginatorFactory $paginatorFactory,
        private readonly FormFactoryInterface $formFactory,
        private readonly EntityManagerInterface $entityManager,
        private readonly TranslatorInterface $translator,
        private readonly \Twig\Environment $engine,
        private readonly UrlGeneratorInterface $urlGenerator,
    ) {}

    #[Route(path: '/{_locale}/person/household/{household_id}/composition/{composition_id}/delete', name: 'chill_person_household_composition_delete')]
    public function deleteAction(Request $request, mixed $household_id, mixed $composition_id): Response
    {
        $composition = $this->householdCompositionRepository->find($composition_id);
        $household = $this->householdRepository->find($household_id);

        $this->denyAccessUnlessGranted(HouseholdVoter::EDIT, $household);

        if (null === $composition) {
            throw $this->createNotFoundException('Unable to find composition entity.');
        }

        $form = $this->createFormBuilder()
            ->setAction($this->generateUrl('chill_person_household_composition_delete', [
                'composition_id' => $composition_id,
                'household_id' => $household_id,
            ]))
            ->add('submit', SubmitType::class, ['label' => 'Delete'])
            ->getForm();

        if (Request::METHOD_POST === $request->getMethod()) {
            $form->handleRequest($request);

            if ($form->isValid()) {
                $this->entityManager->remove($composition);
                $this->entityManager->flush();

                $this->addFlash('success', $this->translator
                    ->trans('The composition has been successfully removed.'));

                return $this->redirectToRoute('chill_person_household_composition_index', [
                    'id' => $household_id,
                ]);
            }
        }

        return $this->render(
            '@ChillPerson/HouseholdComposition/delete.html.twig',
            [
                'household' => $household,
                'composition' => $composition,
                'form' => $form->createView(),
            ]
        );
    }

    #[Route(path: '/{_locale}/person/household/{id}/composition/index', name: 'chill_person_household_composition_index')]
    public function index(Household $household, Request $request): Response
    {
        if (!$this->security->isGranted(HouseholdVoter::SEE, $household)) {
            throw new AccessDeniedException('not allowed to edit a household');
        }

        $count = $this->householdCompositionRepository->countByHousehold($household);
        $paginator = $this->paginatorFactory->create($count);
        $compositions = $this->householdCompositionRepository->findByHousehold(
            $household,
            ['startDate' => 'DESC', 'id' => 'DESC'],
            $paginator->getItemsPerPage(),
            $paginator->getCurrentPageFirstItemNumber()
        );

        return new Response($this->engine->render(
            '@ChillPerson/HouseholdComposition/index.html.twig',
            [
                'household' => $household,
                'compositions' => $compositions,
            ]
        ));
    }

    #[Route(path: '/{_locale}/person/household/{id}/composition/new', name: 'chill_person_household_composition_new')]
    public function newAction(Household $household, Request $request): Response
    {
        if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) {
            $isEdit = $request->query->has('edit');

            if ($isEdit) {
                $householdCompositions = $household->getCompositions()->filter(static fn (HouseholdComposition $composition) => $composition->getId() === $request->query->getInt('edit'));

                if (1 !== $householdCompositions->count()) {
                    throw new BadRequestHttpException('could not find the composition with this id associated to the household');
                }
                $householdComposition = $householdCompositions->first();
            } else {
                $householdComposition = (new HouseholdComposition())
                    ->setStartDate(new \DateTimeImmutable());
            }
            $form = $this->formFactory->create(HouseholdCompositionType::class, $householdComposition);

            $form->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {
                if (!$isEdit) {
                    $this->entityManager->persist($householdComposition);
                    $household->addComposition($householdComposition);
                }

                $this->entityManager->flush();

                $request->getSession()->getFlashBag()->add(
                    'success',
                    $this->translator->trans('household_composition.Composition added')
                );

                return new RedirectResponse(
                    $this->urlGenerator->generate('chill_person_household_composition_index', [
                        'id' => $household->getId(),
                    ])
                );
            }

            if ($form->isSubmitted() && !$form->isValid()) {
                $request->getSession()->getFlashBag()->add(
                    'warning',
                    $this->translator->trans('This form contains errors')
                );
            }
        }

        return new Response($this->engine->render(
            '@ChillPerson/HouseholdComposition/create.html.twig',
            [
                'household' => $household,
                'form' => isset($form) ? $form->createView() : null,
                'isPosted' => isset($form) ? $form->isSubmitted() : false,
                'editId' => $request->query->getInt('edit', -1),
            ]
        ));
    }
}
