<?php

namespace AutoAdmin\Bundle\Admin\Form\Type;

use AutoAdmin\Bundle\Admin\Configuration\ConfigManager;
use AutoAdmin\Bundle\Admin\Form\FormOptionNormalizer;
use AutoAdmin\Bundle\Admin\Form\Type\Component\RichEntityType;
use AutoAdmin\Bundle\Admin\Helper\AccessHelper;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AdminContentType extends AbstractType
{
    private ConfigManager $configManager;
    private FormOptionNormalizer $formOptionNormalizer;
    private AccessHelper $accessHelper;

    public function __construct(
        ConfigManager        $configManager,
        FormOptionNormalizer $formOptionNormalizer,
        AccessHelper         $accessHelper
    )
    {
        $this->configManager = $configManager;
        $this->formOptionNormalizer = $formOptionNormalizer;
        $this->accessHelper = $accessHelper;
    }

    public function getParent(): string
    {
        return AdminFormType::class;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $class = $options['data_class'];
        $entityAction = $options['entity_action'];
        $entityConfig = $this->configManager->getEntityConfigByClass($class);
        $fields = $entityConfig['form'][$entityAction][$options['admin_tab'] ?? 'default'] ?? [];

        foreach ($fields as $k => $field) {
            if (!empty($field['roles']) && $this->accessHelper->isGranted($field['roles']) === false) {
                continue;
            }

            $prop = $field['property'];


            $field['property'] = str_replace('_tr.', '', $prop);
            $formTypeOptions = $this->formOptionNormalizer->normalize($field['type_options']);
            $formTypeOptions = array_merge([
                'property_path' => str_replace('_tr.', 'currentTranslation.', $prop),
                'priority' => $field['priority'] ?? 0,
            ], $formTypeOptions);

            // override default choice label
            if ($field['type'] == RichEntityType::class && $field['choice_label']) {
                $formTypeOptions = $this->setChoiceLabel($field, $formTypeOptions);
            }

            $builder->add($field['property'], $field['type'], $formTypeOptions);
        }

        if ($options['has_submit']) {
            $builder->add('submit', SubmitType::class, ['label' => 'save',]);
            if (empty($options['disable_submit_and_return'])) {
                $builder->add('submit_and_return', SubmitType::class, ['label' => 'save_and_return',]);
            }
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefined('em');
        $resolver->setDefined('query_builder');
        $resolver->setDefault('label', false);
        $resolver->setDefault('has_submit', false);
        $resolver->setDefault('admin_tab', 'default');
        $resolver->setDefault('entity_action', 'update');
    }

    /**
     * @param mixed $field
     * @param array $formTypeOptions
     * @return array
     */
    public function setChoiceLabel(mixed $field, array $formTypeOptions): array
    {
        $formTypeOptions['choice_label'] = function ($choice, $key, $value) use ($field) {
            $choiceObject = clone $choice;

            if (str_contains($field['choice_label'], '_tr.')) {
                $choiceObject = $choice->getCurrentTranslation() ? $choice->getCurrentTranslation() : $choice;
                $field['choice_label'] = str_replace('_tr.', '', $field['choice_label']);
            }

            if (!str_starts_with($field['choice_label'], 'get')) {
                $methodName = 'get' . ucfirst($field['choice_label']);
            } else {
                $methodName = $field['choice_label'];
            }

            if (method_exists($choiceObject, $methodName)) {
                return $choiceObject->{$methodName}();
            } else {
                return $choice;
            }
        };
        return $formTypeOptions;
    }
}
