<?php

namespace App\Form;

use App\Entity\Commune;
use App\Entity\Department;
use App\Entity\User;
use App\Entity\Ministry;
use App\Entity\Direction;
use App\Repository\MinistryRepository;
use App\Repository\DirectionRepository;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class UserType extends AbstractType
{
    private $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email', EmailType::class, [
                'label' => 'basics.email',
            ])
            ->add('givenName', TextType::class, [
                'label' => 'basics.givenName',
            ])
            ->add('familyName', TextType::class, [
                'label' => 'basics.familyName',
            ])
            ->add('telephone', TelType::class, [
                'label' => 'basics.telephone',
                'required' => false,
            ])

            ->add('typestructure', ChoiceType::class, [
                'label' => 'basics.typestructure',
                'choices'  => [
                    'basics.ministry' => 0,
                    'Département' => 2,
                    'basics.commune' => 1,
                ],
                'required' => false,
                'placeholder' => 'basics.typestructure.placeholder',
                'mapped' => false,
                'data' => $options['type'],
                'attr' => array("onchange" => "typestructure(this.value);")
            ])

            ->add('office', TextType::class, [
                'label' => 'basics.office',
                'required' => false,
            ])
            
            ->add('ministry', EntityType::class, [
                'label' => 'basics.ministry',
                'class' => Ministry::class,
                'choice_label' => 'name',
                'placeholder' => 'basics.ministry.placeholder',
                'mapped' => false,
                'required' => false,
                'data' => $options['type']==0 ? $options['structure'] : null, 
                'query_builder' => function(MinistryRepository $repository) use($options) {
                    return $repository->findMinistryByYear(
                        '%'.$options['sessionYear'].'%', 
                        $options['sessionMinistry']
                    );
                },
            ])
            ->add('department', EntityType::class, [
                'label' => 'basics.department',
                'class' => Department::class,
                'placeholder' => 'basics.department.placeholder',
                'required' => false,
            ])
        ;

        if(!$options['with_roles']){
            $builder->add('role', ChoiceType::class, [
                'label' => 'Rôle',
                'choices'  => [
                    'Point focal' => 'ROLE_FOCAL',
                    'SE/DPAF' => 'ROLE_DPP',
                    'DDD' => 'ROLE_DDD',
                    'Manager' => 'ROLE_MANAGER',
                    'Administrateur' => 'ROLE_ADMIN',
                ],
                'placeholder' => 'Sélectionnez un rôle',
                'mapped' => false,
            ]);
        }

        $builder->get('department')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) {
                $form = $event->getForm();
                $this->addCommuneField($form->getParent(), $form->getData());
            }
        );

        $builder->addEventListener(
            FormEvents::POST_SET_DATA,
            function (FormEvent $event) {
                $form = $event->getForm();

                $data = $event->getData();
                $commune = $data->getCommune();
                if ($commune) {
                    $department = $commune->getDepartment();
                    $this->addCommuneField($form, $department);
                    $form->get('department')->setData($department);
                } else {
                    $this->addCommuneField($form, null);
                }
            }
        );

        $builder->get('ministry')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use($options) {
                $form = $event->getForm();
                $this->addDirectionField($form->getParent(), $form->getData(), null, $options);
            }
        );

        $isAdmin = false;
        if ($token = $this->tokenStorage->getToken()) {
            if ($user = $token->getUser()) {
                $isAdmin = $user->hasRole('ROLE_ADMIN');
            }
        }



        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($options, $isAdmin) {
                $form = $event->getForm();
                $user = $event->getData();

                $direction = $user->getDirection(); $commune=null;
                if ($direction) {
                    $ministry = $direction->getMinistry();
                    $this->addDirectionField($form, $ministry, $commune, $options);
                    $form->get('ministry')->setData($ministry);
                } else {
                    $this->addDirectionField($form, null, null, $options);
                }

                if ($isAdmin) {
                    $form
                        ->add('enabled', CheckboxType::class, [
                            'label' => 'basics.enabled',
                            'required' => false
                        ])
                        ;
                }

                if ($isAdmin && $options['with_roles'] && !empty($options['editable_roles'])) {
                    $data = array_filter($user->getRoles(), function ($role) use ($options) {
                        return in_array($role, $options['editable_roles']);
                    });
                    $choices = array_combine($options['editable_roles'], $options['editable_roles']);
                    $event->getForm()->add('roles', ChoiceType::class, [
                        // Use mapped = false for security reasons
                        'mapped' => false,
                        'choices' => $choices,
                        'choice_label' => function ($value, $key, $index) {
                            return "roles.{$key}.help";
                        },
                        'expanded' => true,
                        'multiple' => true,
                        'data' => $data
                    ]);
                }

            }
        );
    }

    private function addCommuneField(FormInterface $form, ?Department $department)
    {
        $form->add('commune', EntityType::class, [
            'label' => 'basics.commune',
            'required' => false,
            'class' => Commune::class,
            'placeholder' => 'basics.commune.placeholder',
            'choices' => $department ? $department->getCommunes() : []
        ]);
    }
    
    private function addDirectionField(FormInterface $form, ?Ministry $ministry,  ?Commune $commune, array $options)
    {
        $form->add('direction', EntityType::class, [
            'label' => 'basics.direction',
            'required' => false,
            'class' => Direction::class,
            'choice_label' => 'name',
            'choices' => $ministry ? $ministry->getDirections() : [],
            'placeholder' => 'basics.direction.placeholder',
            'query_builder' => function (DirectionRepository $repository) use($options, $ministry, $commune) {
                return $repository->findDirectionByYear('%'.$options['sessionYear'].'%', $ministry, $commune);
            },
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
            'sessionYear' => null,
            'sessionMinistry' => null,
            'sessionCommune' => null,
            'with_roles' => false,
            'editable_roles' => [],
            'type' => null,
            'structure' => null,
            ]);
    }
}
