<?php

/*
 * This file is part of the VitiCore 2.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Admin;

use A2lix\TranslationFormBundle\Form\Type\TranslatedEntityType;
use CpCreation\VitiCore\Product\Model\ProductPrice;
use CpCreation\VitiCore\Product\Model\ProductType;
use CpCreation\VitiCore\Product\Model\ProductVariant;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

final class ProductVariantType extends AbstractType
{
    /** @var list<object> */
    private array $groups;

    public function __construct(
        ProductPriceGroupRepository $productPriceGroupRepository,
        private readonly AuthorizationCheckerInterface $authorizationChecker,
    ) {
        // Idéalement: tape le retour du repo en list<ProductPriceGroup>
        $this->groups = $productPriceGroupRepository->findByPositionOrder();
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        if (
            $this->authorizationChecker->isGranted('ROLE_ADMIN')
            || $this->authorizationChecker->isGranted('ROLE_PRODUCT')
        ) {
            $builder
                ->add('type', TranslatedEntityType::class, [
                    'label' => 'Type',
                    'class' => ProductType::class,
                    'translation_property' => 'name',
                    'required' => true,
                    'choice_label' => static function (ProductType $type): string {
                        return $type->getInfo()
                            ? $type->getName().' ('.$type->getInfo().')'
                            : $type->getName();
                    },
                ])
                ->add('byDefault', CheckboxType::class, [
                    'label' => 'Défaut',
                    'required' => false,
                ])
                ->add('lot', IntegerType::class, [
                    'required' => true,
                    'label' => 'Vendu par',
                    'attr' => [
                        'min' => 1,
                    ],
                ])
                ->add('position', HiddenType::class, [
                    'label' => 'position',
                    'required' => false,
                    'attr' => ['class' => 'position-form'],
                ]);
        }

        $builder
            ->add('unPublished', CheckboxType::class, [
                'label' => 'Dépublié',
                'required' => false,
            ])
            ->add('soldOut', CheckboxType::class, [
                'label' => 'Épuisé',
                'required' => false,
            ])
            ->add('stockAt', DateTimeType::class, [
                'required' => false,
                'label' => 'Date renouvellement de stock',
                'input' => 'datetime',
                'format' => 'yyyy-MM-dd HH:mm',
                'html5' => false,
                'widget' => 'single_text',
                'attr' => ['class' => 'datetimepicker'],
            ])
            ->add('stock', NumberType::class, [
                'required' => false,
                'label' => 'Stock de départ',
            ]);

        // On gère "prices" ici uniquement (pas besoin de l'ajouter avant)
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void {
            $variant = $event->getData();
            $form = $event->getForm();

            /** @var list<ProductPrice> $data */
            $data = [];

            if ($variant instanceof ProductVariant) {
                // Index des groupes déjà présents dans la variante
                $existingByGroupId = [];
                foreach ($variant->getPrices() as $price) {
                    $group = $price->getGroup();
                    if ($group && method_exists($group, 'getId') && null !== $group->getId()) {
                        $existingByGroupId[(string) $group->getId()] = true;
                    }
                }

                // Ajoute les prix manquants pour chaque groupe
                foreach ($this->groups as $group) {
                    if (!method_exists($group, 'getId') || null === $group->getId()) {
                        continue;
                    }
                    if (!isset($existingByGroupId[(string) $group->getId()])) {
                        $price = new ProductPrice();
                        $price->setGroup($group);
                        $data[] = $price;
                    }
                }

                // puis on garde les prix existants (en fin de liste)
                $data = array_merge($data, $variant->getPrices()->toArray());
            } else {
                // Nouvelle variante: un prix par groupe
                foreach ($this->groups as $group) {
                    $price = new ProductPrice();
                    $price->setGroup($group);
                    $data[] = $price;
                }
            }

            if ($form->has('prices')) {
                $form->remove('prices');
            }

            $form->add('prices', PriceCollectionType::class, [
                'entry_type' => ProductPriceType::class,
                'label' => false,
                'allow_add' => true,
                'allow_delete' => false,
                'prototype' => true,
                'by_reference' => false,
                'data' => $data,
                'entry_options' => [
                    'data_class' => ProductPrice::class,
                    'label' => false,
                ],
            ]);
        });
    }

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