<?php

namespace App\Form;

use App\Entity\Tag;
use App\Repository\TagRepository;
use Doctrine\Common\Collections\Collection;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class TagsType extends AbstractType implements DataTransformerInterface
{
    public function __construct(
        private readonly TagRepository      $repository,
        private readonly Security           $security,
        private readonly ValidatorInterface $validator,
    ) {}

    public function transform($value): string
    {
        if ($value === null) {
            return '';
        }

        if ($value instanceof Collection) {
            $value = $value->toArray();
        }

        if (is_array($value)) {
            $tags = array_map(fn(Tag $tag) => $tag->name, $value);
        } else {
            return '';
        }
        return implode(', ', $tags);
    }

    public function reverseTransform($value): array
    {
        $tags = array_filter(array_map('trim', explode(',', $value)));
        $user = $this->security->getUser();

        $tagEntities = [];
        foreach ($tags as $tag) {
            $tagEntity = $this->repository->findOneBy(['name' => $tag, 'user' => $user]);
            if ($tagEntity === null) {
                $tagEntity = new Tag();
                $tagEntity->name = $tag;
                $tagEntity->user = $user;

                // Validate the new Tag entity
                $errors = $this->validator->validate($tagEntity);
                if (count($errors) > 0) {
                    $exception = new TransformationFailedException();
                    $exception->setInvalidMessage(implode(', ', array_map(
                        fn(ConstraintViolationInterface $error) => $error->getMessage(),
                        iterator_to_array($errors)
                    )));
                    throw $exception;
                }

                $this->repository->save($tagEntity);
            }
            $tagEntities[] = $tagEntity;
        }

        return $tagEntities;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->addModelTransformer($this);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => null, // No specific entity class
            'label' => 'Tags (comma-separated)',
            'required' => false,
        ]);
    }

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