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

use Chill\EventBundle\Entity\Event;
use Chill\EventBundle\Entity\EventType;
use Chill\EventBundle\Repository\EventACLAwareRepositoryInterface;
use Chill\EventBundle\Repository\EventTypeRepository;
use Chill\EventBundle\Security\EventVoter;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Pagination\PaginatorFactoryInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactory;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;

final class EventListController extends AbstractController
{
    public function __construct(
        private readonly Environment $environment,
        private readonly EventACLAwareRepositoryInterface $eventACLAwareRepository,
        private readonly EventTypeRepository $eventTypeRepository,
        private readonly FilterOrderHelperFactory $filterOrderHelperFactory,
        private readonly FormFactoryInterface $formFactory,
        private readonly PaginatorFactoryInterface $paginatorFactory,
        private readonly TranslatableStringHelperInterface $translatableStringHelper,
        private readonly UrlGeneratorInterface $urlGenerator,
        private readonly AuthorizationHelper $authorizationHelper,
    ) {}

    #[Route(path: '{_locale}/event/event/list', name: 'chill_event_event_list')]
    public function __invoke(): Response
    {
        $filter = $this->buildFilterOrder();
        $filterData = [
            'q' => (string) $filter->getQueryString(),
            'dates' => $filter->getDateRangeData('dates'),
            'event_types' => $filter->getEntityChoiceData('event_types'),
            'responsables' => $filter->getUserPickerData('responsables'),
            'centers' => $filter->getEntityChoiceData('centers'),
        ];
        $total = $this->eventACLAwareRepository->countAllViewable($filterData);
        $pagination = $this->paginatorFactory->create($total);
        $events = $this->eventACLAwareRepository->findAllViewable($filterData, $pagination->getCurrentPageFirstItemNumber(), $pagination->getItemsPerPage());
        $eventForms = [];
        foreach ($events as $event) {
            $eventForms[$event->getId()] = $this->createAddParticipationByPersonForm($event)->createView();
        }

        return new Response($this->environment->render(
            '@ChillEvent/Event/page_list.html.twig',
            [
                'events' => $events,
                'pagination' => $pagination,
                'eventForms' => $eventForms,
                'filter' => $filter,
            ]
        ));
    }

    private function buildFilterOrder(): FilterOrderHelper
    {
        $types = $this->eventTypeRepository->findAllActive();
        $centers = $this->authorizationHelper->getReachableCenters($this->getUser(), EventVoter::SEE);

        $builder = $this->filterOrderHelperFactory->create(__METHOD__);
        $builder
            ->addDateRange('dates', 'event.filter.event_dates')
            ->addSearchBox(['name'])
            ->addEntityChoice('event_types', 'event.filter.event_types', EventType::class, $types, [
                'choice_label' => fn (EventType $e) => $this->translatableStringHelper->localize($e->getName()),
                'expanded' => false,
                'required' => false,
                'attr' => ['class' => 'select2'],
            ])
            ->addUserPicker('responsables', 'event.filter.pick_responsable', ['multiple' => true, 'required' => false])
            ->addEntityChoice('centers', 'event.filter.center', Center::class, $centers, [
                'choice_label' => fn (Center $c) => $c->getName(),
                'expanded' => false,
                'required' => false,
                'attr' => ['class' => 'select2'],
            ]);

        return $builder->build();
    }

    private function createAddParticipationByPersonForm(Event $event): FormInterface
    {
        $builder = $this->formFactory
            ->createNamedBuilder(
                '',
                FormType::class,
                null,
                [
                    'method' => 'GET',
                    'action' => $this->urlGenerator->generate('chill_event_participation_new'),
                    'csrf_protection' => false,
                ]
            );

        $builder->add('person_id', PickPersonDynamicType::class, [
            'as_id' => true,
            'multiple' => false,
            'submit_on_adding_new_entity' => true,
            'label' => 'Add a participation',
        ]);

        $builder->add('event_id', HiddenType::class, [
            'data' => $event->getId(),
        ]);

        return $builder->getForm();
    }
}
