<?php

namespace PrestaShop\Module\PolarisPrestaConnector\Forms;

use PrestaShop\Module\PolarisPrestaConnector\SyncConfiguration;
use PrestaShopBundle\Form\Admin\Type\CustomContentType;
use PrestaShopBundle\Form\Admin\Type\CategoryChoiceTreeType;
use Symfony\Component\Form\FormBuilderInterface;
use PrestaShopBundle\Form\Admin\Type\SwitchType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class CatalogType extends ConnectorType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $backofficeName = $this->module->getBridge()->getId();
        $cfg = $this->module->getCfg();

        $supportedOptionalFeatures = $this->module->getBridge()->getSupportedOptionalFeatures();

        $builder->add('title_stock', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => false,
                'title' => 'Fonctionnalités de catalogue',
                'help' => '',
            ],
        ]);
            
        $builder->add("use_mpm", SwitchType::class, [
                'label' => "Afficher le sélecteur de produits connexes sur la fiche produit",
                'help' => "Si votre produit est déclinée en plusieurs variantes sous ".$backofficeName.", affichez toutes les variantes possible sous forme de miniatures à cliquer.",
                'required' => false,
                'data' => \Configuration::get($this->module->BridgePrefix."prestaconnector_use_mpm"), // valeur par défaut selon l'option configurée
            ]);

        $builder->add("use_availabilities", SwitchType::class, [
                'label' => "Afficher la disponibilité des pièces dans les magasins",
                'help' => "Génère et affiche un tableau de disponibilité des pièces dans chaque magasins sur la fiche produit.",
                'required' => false,
                'data' => \Configuration::get($this->module->BridgePrefix."prestaconnector_use_availabilities"), 
            ]);

        /**
         * Valeur de dernières pièces disponibles
         */
        $builder
            ->add('availability_trigger', TextType::class, [
                'label' => 'Dernières pièces disponibles',                                
                'required' => false,
                'help' => 'A partir de quelle quantité de stock le produit est considéré comme étant en disponibilité limitée ?',
                'data' => \Configuration::get($this->module->BridgePrefix."prestaconnector_availability_trigger"),
            ]);

        /**
         * CFG_PR_ATTRIBUTES_MAPPING
         */
        $productMapping = $cfg->get(SyncConfiguration::CFG_PR_ATTRIBUTES_MAPPING) ?? [];
        $colorMapping = $cfg->get(SyncConfiguration::CFG_MAP_COLOR_ATTRS) ?? [];
        $productAttrs = $cfg->get(SyncConfiguration::CFG_DYN_ATTR) ?? [];
        $productProps = $cfg->get(SyncConfiguration::CFG_DYN_PROP) ?? [];
        $productAttrsExtended = array_merge($productAttrs, $cfg->get(SyncConfiguration::CFG_DYN_CAT));

        /** Mapping des produits */
        $builder->add('title_product_mapping', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Attributs discriminants',
                'help' => '<p>
                                Sélectionnez les attributs '.$backofficeName.' que vous souhaitez utiliser comme discriminants de produit Prestashop (cf. documentation).<br>
                                <em>Par exemple, si vous désirez créer un produit Prestashop par couleur, activez "couleur".</em>
                                <br>
                                <em><strong>Notes : les attributs non mappés sont obligatoirement discriminants.</strong></em>
                            </p>',
            ],
        ]);

        // Création dynamique des champs en fonction des options de configuration
        foreach ($productAttrs as $k => $name)
        {
            if (isset($productProps[$k]) && $productProps[$k])
                continue; // Cet attribut est non discriminant, on ne le propose pas ici
            $safe_key = 'PRODUCT_ATTR_PRODUCT_'.trim(base64_encode($k), '=');
            $builder->add($safe_key, SwitchType::class, [
                'label' => $name,
                'required' => false,
                'data' => $productMapping[SyncConfiguration::PRODUCT_ATTR_PRODUCT][$k] ?? false, // valeur par défaut selon l'option configurée
            ]);
        }

        /** Mapping des attributs */
        $builder->add('title_attribute_mapping', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Mappage des attributs de produit',
                'help' => '<p>
                                Les attributs de produit vous permettent d\'ajouter des propriétés à vos déclinaisons pour les différencier (matière, couleur, etc.) et non de le catégoriser : 
                                <ul>
                                    <li>quoique vous renseignez ci-dessous, votre produit sera catégorisé en fonction des options de mappage qui sont définies dans le mappings ;</li>
                                    <li>quand un groupe d\'attributs est mappée ici, le module créera les attributs dans Prestashop quand ils sont utilisés par un produit et qu\'ils n\'existent pas déjà ;</li>
                                </ul>
                                Pour chaque type d\'attributs de votre back-office '.$backofficeName.' sélectionnez le <strong>groupe d\'attributs Prestashop</strong> dans lequel vous souhaitez reporter la valeur.
                                <br>
                                Si vous indiquez "---", l\'attribut ne sera pas synchronisé dans un groupe d\'attributs.
                            </p>',
            ],
        ]);

        // Création dynamique des champs en fonction des options de configuration
        $attributeGroups = ['---' => 0];

        // Pour empêcher les erreurs, on retire tous les groupes d'attributs qui ont été affectés à des tailles
        $sizeGrids = $cfg->get(SyncConfiguration::CFG_MAP_SIZEGRIDS) ?? [ '*' => -1 ];

        foreach (\AttributeGroup::getAttributesGroups(\Context::getContext()->language->id) as $ag)
            if (!in_array($ag['id_attribute_group'], $sizeGrids))
                $attributeGroups[$ag['name']] = $ag['id_attribute_group'];

        foreach ($productAttrsExtended as $k => $name)
        {            
            $safe_key = 'PRODUCT_ATTR_VARIANT_'.trim(base64_encode($k), '=');
            
            $builder->add($safe_key, ChoiceType::class, [
                'label' => $name,
                'required' => false,
                'expanded' => false,
                'multiple' => false,
                'empty_data' => 0,
                'choices' => $attributeGroups,
                'data' => $productMapping[SyncConfiguration::PRODUCT_ATTR_VARIANT][$k] ?? 0, // valeur par défaut selon l'option configurée
            ]);
        }

        /** Nettoyage automatique des attributs non utilisés */
        $builder->add('ATTR_AUTO_CLEAN', SwitchType::class, [
            'label' => 'Nettoyage automatique des attributs non utilisés',
            'help' => 'Indique si le module doit chercher et supprimer les attributs des groupes renseignés ci-dessus lorsqu\'ils ne sont plus utilisés par aucun de vos produits. Cette opération est faite au cours de la procédure de nettoyage qui a lieu une fois par semaine.',
            'required' => false,
            'disabled' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_ATTR_AUTO_CLEAN) ?? false, // valeur par défaut selon l'option configurée
        ]);

        /** Mapping des caractéristiques */
        $builder->add('title_features_mapping', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Mappage des caractéristiques de produit',
                'help' => '<p>
                                Les caractéristiques de produit vous permettent d\'ajouter des propriétés à vos produits (lavable en machine, nuance de couleur, matière, etc.) et non de le catégoriser : 
                                <ul>
                                    <li>quoique vous renseignez ci-dessous, votre produit sera catégorisé en fonction des options de mappage qui sont définies dans le mappings ;</li>
                                    <li>quand une caractéristique est mappé, le module créera les entrées dans Prestashop quand elles sont nécessaires pour un produit et qu\'elles n\'existent pas déjà ;</li>
                                </ul>
                                Pour chaque type d\'attributs de votre back-office '.$backofficeName.' sélectionnez la <strong>caractéristique Prestashop</strong> dans laquelle vous souhaitez reporter la valeur.
                                <br>
                                Si vous n\'indiquez "---", l\'attribut ne sera pas synchronisé dans une caractéristique.
                            </p>',
            ],
        ]);

        // Création dynamique des champs en fonction des options de configuration
        $features = ['---' => 0];
        foreach (\Feature::getFeatures(\Context::getContext()->language->id) as $feat)
            $features[$feat['name']] = $feat['id_feature'];

        foreach ($productAttrsExtended as $k => $name)
        {
            $safe_key = 'PRODUCT_ATTR_FEATURE_'.trim(base64_encode($k), '=');
            $builder->add($safe_key, ChoiceType::class, [
                'label' => $name,
                'required' => false,
                'expanded' => false,
                'multiple' => false,
                'empty_data' => 0,
                'choices' => $features,
                'data' => $productMapping[SyncConfiguration::PRODUCT_ATTR_FEATURE][$k] ?? 0, // valeur par défaut selon l'option configurée
            ]);
        }

        /** Mapping des couleurs */
        $builder->add('title_colors_mapping', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Mappage des couleurs',
                'help' => '<p>
                                Lorsqu\'elle est activée, cette option vous permet de substituer la couleur de votre back-office '.$backofficeName.' par une couleur Prestashop (les correspondances sont définissables dans les mappages catalogue).<br>
                                Cette option est utile si vous avez renseigné des nuances sur votre backoffice (jaune moutarde, bordeaux, bleu marine, etc.) et que vous souhaitez les remplacer par des couleurs standardisées (jaune, rouge, bleu, etc.) afin
                                de limiter le nombre de filtres couleurs. <br>
                                Les couleurs du style <code>bleu/blanc</code> sont systématiquement remplacées par la couleur "multicolore" dans Prestashop.
                            </p><p>
                                Pour chaque information de couleur de votre back-office '.$backofficeName.' sélectionnez le <strong>groupe d\'attributs Prestashop</strong> dans laquelle vous souhaitez reporter la valeur standardisée.
                            </p>',
            ],
        ]);

        foreach ($productAttrsExtended as $k => $name)
        {
            $safe_key = 'PRODUCT_MAP_COLOR_ATTR_'.trim(base64_encode($k), '=');
            
            $builder->add($safe_key, ChoiceType::class, [
                'label' => $name,
                'required' => false,
                'expanded' => false,
                'multiple' => false,
                'empty_data' => 0,
                'choices' => $attributeGroups,
                'data' => ($colorMapping[$k] ?? 0) ?: 0, // valeur par défaut selon l'option configurée
            ]);
        }

        if (in_array(SyncConfiguration::CFG_PRODUCT_IMPORT_ONLY_WITH_STOCK, $supportedOptionalFeatures))
        {
            /**
             * Options de synchronisation des fiches produits
             */
            $builder->add('title_sync_filtre', CustomContentType::class, [
                'label' => false,
                'template' => $this->titleFormTemplatePath,
                'data' => [
                    'hr' => true,
                    'title' => 'Filtres',
                    'help' => '<p>Des filtres supplémentaires sont disponibles pour l\'importation de vos produits depuis votre Backoffice.</p>',
                ],
            ]);
            
            $builder->add('WITH_STOCK_ONLY', SwitchType::class, [
                'label' => 'N\'importer que les produits en stock lorsqu\'ils n\'existent pas déjà sous Prestashop.',
                //'help' => $optionsDesc[$field]['description'],  // Utilisation de la description pour l'aide                
                'required' => false,
                'data' => $cfg->get(SyncConfiguration::CFG_PRODUCT_IMPORT_ONLY_WITH_STOCK) ?? false, // valeur par défaut selon l'option configurée
            ]);
        }

        
        /**
         * Options constructions produits 
         */
        $varsList = ['nom', 'marque'];
        // On ajoute à varsList tous les attributs tirés de la configuration
        foreach ($productAttrsExtended as $k => $name)
            $varsList[] = $name;

        $vars = '<code>{{' . join('}}</code>, <code>{{', $varsList) . '}}</code>';
        
        $builder->add('title_misc', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Nom de produit',
                'help' => '<p>Indiquez ici comment sont construits les noms de vos produits quand ils sont synchronisés automatiquement. Vous pouvez utiliser les variables suivantes : ' . $vars . ' </p>',
            ],
        ]);

        $builder->add(SyncConfiguration::CFG_PRODUCT_NAME_TEMPLATE, TextType::class, [
            'label' => 'Construction de nom de produit',
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_PRODUCT_NAME_TEMPLATE) ?? '',
            'help' => 'Utilisez des variables comme {{nom}}, {{marque}}, {{couleur}}, etc. pour construire le nom du produit ou laissez vide juste pour le nom par défaut.',
        ]);

        $builder->add('title_default_map', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Affectation de la catégorie par défaut',
                'help' => '<p>Quand cette option est renseignée, le module affectera au produit une catégorie par défaut. Pour la choisir, il privilégiera la catégorie la plus profonde parmi les enfants des catégories mères sélectionnées ci-dessous. A défaut, il choisira la catégorie la plus profonde.</p>',
            ],
        ]);

        $builder->add(SyncConfiguration::CFG_DEFAULT_ROOT_CATEGORIES, CategoryChoiceTreeType::class, [
            'label' => 'Catégories mères des catégories par défaut',
            'data' => $cfg->get(SyncConfiguration::CFG_DEFAULT_ROOT_CATEGORIES) ?? [], // valeur par défaut selon l'option configurée
            'multiple' => true,
            'required' => false,
            'attr' => [
                'class' => 'js-category-tree-list category-tree',
            ],
        ]);

        /**
         * Options de synchronisation des fiches produits
         */
        $builder->add('title_sync', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Données produits synchronisées',
                'help' => '<p>Sélectionnez ici les informations que vous désirez synchroniser depuis votre back-office Polaris vers votre boutique en ligne :</p>
                            <ul>
                                <li>les informations sélectionnées sont systématiquement remplacées par celles de votre back-office lors de la synchronisation du produit ;</li>
                                <li>celles qui ne le sont pas sont uniquement positionnées lors de la création du produit.</li>
                            </ul>
                            ',
            ],
        ]);
        
        $cfgOptions = $cfg->get(SyncConfiguration::CFG_DATA_SYNC);        
        $optionsDesc = $cfg->describeSyncConfiguration();
        $mode = $cfg->get(SyncConfiguration::CFG_WORKMODE);

        // Création dynamique des champs en fonction des options de configuration
        foreach ($optionsDesc as $field => $p)
        {
            $isActive = isset($cfgOptions[$field]) ? $cfgOptions[$field] : false;
            $builder->add($field, SwitchType::class, [
                'label' => $p['label'],
                'help' => $p['description'],  // Utilisation de la description pour l'aide                
                'required' => false,
                'disabled' => $mode === 0,
                'data' => $isActive, // valeur par défaut selon l'option configurée
            ]);
        }
        
        $this->module->getBridge()->hookAdminForm($builder, $options);

        // Bouton de sauvegarde
        $builder->add('Enregistrer', SubmitType::class, [
            'attr' => ['class' => 'btn-form-valid btn-primary']
        ]);
    }
}