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

use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Form\Type\PickAsideActivityCategoryType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Form\Type\PickUserLocationType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class AsideActivityFormType extends AbstractType
{
    private readonly array $timeChoices;
    private readonly bool $showConcernedPersonsCount;

    public function __construct(
        ParameterBagInterface $parameterBag,
    ) {
        $this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
        $this->showConcernedPersonsCount = $parameterBag->get('chill_aside_activity.show_concerned_persons_count');
    }

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

        foreach ($this->timeChoices as $e) {
            $timeChoices[$e['label']] = $e['seconds'];
        }

        $durationTimeTransformer = new DateTimeToTimestampTransformer('GMT', 'GMT');
        $durationTimeOptions = [
            'choices' => $timeChoices,
            'placeholder' => 'Choose the duration',
        ];

        $builder
            ->add('agent', PickUserDynamicType::class, [
                'label' => 'For agent',
                'required' => true,
            ])
            ->add(
                'date',
                ChillDateType::class,
                [
                    'label' => 'date',
                    'data' => new \DateTime(),
                    'required' => true,
                ]
            )
            ->add('type', PickAsideActivityCategoryType::class, [
                'label' => 'Type',
                'required' => true,
            ])
            ->add('duration', ChoiceType::class, $durationTimeOptions)
            ->add('note', ChillTextareaType::class, [
                'label' => 'Note',
                'required' => false,
            ])
            ->add('location', PickUserLocationType::class)
        ;

        if ($this->showConcernedPersonsCount) {
            $builder->add('concernedPersonsCount', IntegerType::class, [
                'label' => 'Concerned persons count',
                'required' => false,
                'attr' => [
                    'min' => 0,
                ],
            ]);
        }

        foreach (['duration'] as $fieldName) {
            $builder->get($fieldName)
                ->addModelTransformer($durationTimeTransformer);

            $builder->get($fieldName)
                ->addEventListener(FormEvents::PRE_SET_DATA, static function (FormEvent $formEvent) use (
                    $timeChoices,
                    $builder,
                    $durationTimeTransformer,
                    $durationTimeOptions,
                    $fieldName
                ) {
                    // set the timezone to GMT, and fix the difference between current and GMT
                    // the datetimetransformer will then handle timezone as GMT
                    $timezoneUTC = new \DateTimeZone('GMT');
                    /** @var \DateTimeImmutable $data */
                    $data = $formEvent->getData() ?? \DateTime::createFromFormat('U', '300');
                    $seconds = $data->getTimezone()->getOffset($data);
                    $data->setTimeZone($timezoneUTC);
                    $data->add(new \DateInterval('PT'.$seconds.'S'));

                    // test if the timestamp is in the choices.
                    // If not, recreate the field with the new timestamp
                    if (!\in_array($data->getTimestamp(), $timeChoices, true)) {
                        // the data are not in the possible values. add them
                        $timeChoices[$data->format('H:i')] = $data->getTimestamp();
                        $form = $builder->create($fieldName, ChoiceType::class, [...$durationTimeOptions, 'choices' => $timeChoices, 'auto_initialize' => false]);
                        $form->addModelTransformer($durationTimeTransformer);
                        $formEvent->getForm()->getParent()->add($form->getForm());
                    }
                });
        }
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => AsideActivity::class,
        ]);
    }

    public function getBlockPrefix(): string
    {
        return 'chill_asideactivitybundle_asideactivity';
    }
}
