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

use Chill\CustomFieldsBundle\Form\Type\CustomFieldType;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Form\Type\PickCivilityType;
use Chill\MainBundle\Form\Type\Select2CountryType;
use Chill\MainBundle\Form\Type\Select2LanguageType;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Actions\PersonEdit\PersonEditDTO;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\PersonPhone;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
use Chill\PersonBundle\Form\Type\PersonPhoneType;
use Chill\PersonBundle\Form\Type\PickAdministrativeStatusType;
use Chill\PersonBundle\Form\Type\PickEmploymentStatusType;
use Chill\PersonBundle\Form\Type\PickGenderType;
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PersonType extends AbstractType
{
    /**
     * array of configuration for person_fields.
     *
     * Contains whether we should add fields some optional fields (optional per
     * instance)
     *
     * @var string[]
     */
    protected $config = [];

    /**
     * @var ConfigPersonAltNamesHelper
     */
    protected $configAltNamesHelper;

    /**
     * @param string[] $personFieldsConfiguration configuration of visibility of some fields
     */
    public function __construct(
        array $personFieldsConfiguration,
        ConfigPersonAltNamesHelper $configAltNamesHelper,
        protected TranslatableStringHelperInterface $translatableStringHelper,
    ) {
        $this->config = $personFieldsConfiguration;
        $this->configAltNamesHelper = $configAltNamesHelper;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName', TextType::class, ['empty_data' => ''])
            ->add('lastName', TextType::class, ['empty_data' => ''])
            ->add('birthdate', ChillDateType::class, [
                'required' => false,
            ])
            ->add('deathdate', DateType::class, [
                'required' => false,
                'input' => 'datetime_immutable',
                'widget' => 'single_text',
            ])
            ->add('gender', PickGenderType::class, [
                'required' => true,
            ])
            ->add('genderComment', CommentType::class, [
                'required' => false,
            ])
            ->add('numberOfChildren', IntegerType::class, [
                'required' => false,
                'attr' => ['min' => 0],
            ]);

        if ($this->configAltNamesHelper->hasAltNames()) {
            $builder->add('altNames', PersonAltNameType::class, [
                'by_reference' => false,
            ]);
        }

        if ('visible' === $this->config['memo']) {
            $builder
                ->add('memo', ChillTextareaType::class, ['required' => false, 'empty_data' => '']);
        }

        if ('visible' === $this->config['employment_status']) {
            $builder
                ->add('employmentStatus', PickEmploymentStatusType::class, ['required' => false]);
        }

        if ('visible' === $this->config['administrative_status']) {
            $builder
                ->add('administrativeStatus', PickAdministrativeStatusType::class, ['required' => false]);
        }

        if ('visible' === $this->config['place_of_birth']) {
            $builder->add('placeOfBirth', TextType::class, [
                'required' => false,
                'attr' => ['style' => 'text-transform: uppercase;'],
                'empty_data' => '',
            ]);

            $builder->get('placeOfBirth')->addModelTransformer(new CallbackTransformer(
                static fn ($string) => strtoupper((string) $string),
                static fn ($string) => strtoupper((string) $string)
            ));
        }

        if ('visible' === $this->config['contact_info']) {
            $builder->add('contactInfo', ChillTextareaType::class, [
                'required' => false, 'empty_data' => '', 'label' => 'Notes on contact information',
            ]);
        }

        if ('visible' === $this->config['phonenumber']) {
            $builder
                ->add(
                    'phonenumber',
                    ChillPhoneNumberType::class,
                    [
                        'required' => false,
                        'type' => \libphonenumber\PhoneNumberType::FIXED_LINE,
                    ]
                );
        }

        if ('visible' === $this->config['mobilenumber']) {
            $builder
                ->add(
                    'mobilenumber',
                    ChillPhoneNumberType::class,
                    [
                        'type' => \libphonenumber\PhoneNumberType::MOBILE,
                        'required' => false,
                    ]
                )
                ->add('acceptSms', CheckboxType::class, [
                    'required' => false,
                ]);
        }

        $builder->add('otherPhonenumbers', ChillCollectionType::class, [
            'entry_type' => PersonPhoneType::class,
            'button_add_label' => 'Add new phone',
            'button_remove_label' => 'Remove phone',
            'required' => false,
            'allow_add' => true,
            'allow_delete' => true,
            'by_reference' => false,
            'label' => false,
            'delete_empty' => static fn (?PersonPhone $pp = null) => null === $pp || $pp->isEmpty(),
            'error_bubbling' => false,
            'empty_collection_explain' => 'No additional phone numbers',
        ]);

        if ('visible' === $this->config['email']) {
            $builder
                ->add('email', EmailType::class, ['required' => false, 'empty_data' => '']);
        }

        if ('visible' === $this->config['acceptEmail']) {
            $builder
                ->add('acceptEmail', CheckboxType::class, ['required' => false, 'empty_data' => '']);
        }

        if ('visible' === $this->config['country_of_birth']) {
            $builder->add('countryOfBirth', Select2CountryType::class, [
                'required' => false,
            ]);
        }

        if ('visible' === $this->config['nationality']) {
            $builder->add('nationality', Select2CountryType::class, [
                'required' => false,
            ]);
        }

        if ('visible' === $this->config['spoken_languages']) {
            $builder->add('spokenLanguages', Select2LanguageType::class, [
                'required' => false,
                'multiple' => true,
            ]);
        }

        if ('visible' === $this->config['civility']) {
            $builder
                ->add('civility', PickCivilityType::class, [
                    'required' => false,
                    'label' => 'Civility',
                    'placeholder' => 'choose civility',
                ]);
        }

        if ('visible' === $this->config['marital_status']) {
            $builder
                ->add('maritalStatus', Select2MaritalStatusType::class, [
                    'required' => false,
                ])
                ->add('maritalStatusDate', ChillDateType::class, [
                    'required' => false,
                ])
                ->add('maritalStatusComment', CommentType::class, [
                    'required' => false,
                ]);
        }

        $builder->add('identifiers', PersonIdentifiersType::class, [
            'by_reference' => false,
        ]);

        if ($options['cFGroup']) {
            $builder
                ->add(
                    'cFData',
                    CustomFieldType::class,
                    ['attr' => ['class' => 'cf-fields'], 'group' => $options['cFGroup']]
                );
        }
    }

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

        $resolver->setRequired([
            'cFGroup',
        ]);

        $resolver->setAllowedTypes(
            'cFGroup',
            ['null', \Chill\CustomFieldsBundle\Entity\CustomFieldsGroup::class]
        );
    }

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