<?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\Form\Type;

use Chill\EventBundle\Entity\EventType;
use Chill\EventBundle\Entity\Status;
use Chill\EventBundle\Repository\StatusRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Allow to pick amongst type.
 *
 * parameters :
 *
 * - event_type : restricts to a certain event type. Default null (= all event types)
 * - active_only: restricts to active type only. Default true
 */
final class PickStatusType extends AbstractType
{
    public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper, protected TranslatorInterface $translator, protected StatusRepository $statusRepository) {}

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $qb = $options['query_builder'];

        if ($options['event_type'] instanceof EventType) {
            $options['query_builder']->where($qb->expr()->eq('r.type', ':event_type'))
                ->setParameter('event_type', $options['event_type']);
        }

        if (true === $options['active_only']) {
            $options['query_builder']->andWhere($qb->expr()->eq('r.active', ':active'))
                ->setParameter('active', true);
        }

        if (null === $options['group_by'] && null === $options['event_type']) {
            $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) {
                    $form = $event->getForm();
                    $name = $form->getName();
                    $config = $form->getConfig();
                    $type = $config->getType()->getBlockPrefix();
                    $options = $config->getOptions();
                    $form->getParent()->add($name, $type, array_replace($options, [
                        'group_by' => fn (Status $s) => $this->translatableStringHelper->localize($s->getType()->getName()),
                    ]));
                }
            );
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        // create copy for use in Closure
        $translatableStringHelper = $this->translatableStringHelper;
        $translator = $this->translator;

        $resolver
              // add option "event_type"
            ->setDefined('event_type')
            ->setAllowedTypes('event_type', ['null', EventType::class])
            ->setDefault('event_type', null)
            // add option allow unactive
            ->setDefault('active_only', true)
            ->setAllowedTypes('active_only', ['boolean']);

        $qb = $this->statusRepository->createQueryBuilder('r');

        $resolver->setDefaults([
            'class' => Status::class,
            'query_builder' => $qb,
            'group_by' => null,
            'choice_attr' => static fn (Status $s) => [
                'data-event-type' => $s->getType()->getId(),
                'data-link-category' => $s->getType()->getId(),
            ],
            'choice_label' => static fn (Status $s) => $translatableStringHelper->localize($s->getName()).
                      (true === $s->getActive() ? '' :
                            ' ('.$translator->trans('unactive').')'),
        ]);
    }

    public function getParent()
    {
        return EntityType::class;
    }
}
