<?php

namespace PrestaShop\Module\LCVPrestaConnector\Forms;

use PrestaShop\Module\LCVPrestaConnector\SyncConfiguration;
use PrestaShopBundle\Form\Admin\Type\CustomContentType;
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;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class InformationType extends ConnectorType 
{
    /**
     * Instance d'un formulaire de configuration
     * 
     * @param UrlGeneratorInterface $urlGenerator
     */
    public function __construct(private UrlGeneratorInterface $urlGenerator)
    {
        parent::__construct();
    }

    /**
     * Construction du formulaire de configuration des informations
     * 
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $cfg = $this->module->getCfg();

        $backofficeName = $this->module->getBridge()->getId();

        $login = $cfg->get(SyncConfiguration::CFG_LOGIN);

        $lasts_sync = $cfg->get(SyncConfiguration::CFG_SYNCS_LAST);

        $guard = $cfg->get(SyncConfiguration::CFG_GUARD_TOKEN);

        // Si on est sur une version 8 de Prestashop, alors il y a un bug avec UrlGeneratorInterface qui passe en ABSOLUTE_PATH au lieu de ABSOLUTE_URL, on force donc le token à vide qui bypass le bug
        if (version_compare(_PS_VERSION_, '9.0.0', '<')) 
        {                    
            $token_cfg = getenv(\PrestaShop\PrestaShop\Core\Feature\TokenInUrls::ENV_VAR);
            putenv(\PrestaShop\PrestaShop\Core\Feature\TokenInUrls::ENV_VAR.'='.\PrestaShop\PrestaShop\Core\Feature\TokenInUrls::DISABLED);

            // Génération de l'URL absolue via le routeur symfony sans token
            $cronUrl = $this->urlGenerator->generate(
                '_' . $this->module->name . '_cron',
                ['guard' => $guard],
                UrlGeneratorInterface::ABSOLUTE_URL
            );

            putenv(\PrestaShop\PrestaShop\Core\Feature\TokenInUrls::ENV_VAR.'='.$token_cfg);
        }
        else
        {
            // Génération de l'URL absolue via le routeur symfony sans token
            $cronUrl = $this->urlGenerator->generate(
                '_' . $this->module->name . '_cron',
                ['guard' => $guard],
                UrlGeneratorInterface::ABSOLUTE_URL
            );
        }

        // Suppression du token de l'URL ($token)
        $cronUrl = preg_replace('/(\?|&)_token=[^&]+/', '', $cronUrl);

        // Calcul du chemin de la commande CLI pour la synchronisation, qui est une alternative à l'appel HTTP du cron.. sans ".." à l'intérieur du chemin pour éviter les problèmes de sécurité liés à la validation du chemin dans certains environnements d'hébergement        
        $cliPath = _PS_ROOT_DIR_ . '/bin/console '.strtolower($this->module->getBridge()->getId()) . 'prestaconnector:sync';
        $backofficeVersion = $cfg->get(SyncConfiguration::CFG_BACKOFFICE_VERSION) ?? '?';
        $isOutdated = $this->module->getBridge()->isOutdatedBackoffice();

        $builder
        ->add('title_sync', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => false,
                'title' => 'Synchronisation avec le backoffice',
                'help' => '<p>                                
                                Actuellement, votre site Internet est lié au backoffice suivant : 
                           </p>   
                           <div class="bo_infos">
                            <pre class="bo_url">'.$login['address'].'</pre>'.
                           '<pre class="bo_version '.($isOutdated ? 'outdated' : 'up-to-date').'">version ' . $backofficeVersion . ($isOutdated ? '&nbsp;⚠️' : '') . '</pre>'.
                            ($isOutdated ? '<p class="warning"><strong>⚠️&nbsp;→ Ce backoffice est dans une version obsolète ou non compatible avec cette version du module</strong>, certaines fonctionnalités peuvent ne pas être disponibles ou fonctionner de manière erratique. Veuillez contacter notre support pour mettre à jour votre backoffice.</p>' : '').
                           '</div>',
            ],
        ])

        ->add('synchro_active', SwitchType::class, [
            'label'=>'Synchronisation activée',
            'label_attr' => ['class' => 'label-mode'],
            // Indice pour l'utilisateur sur ce que fait le mode basique et le mode complet 
            'help' => 'Active ou désactive la synchronisation des données.',            
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_ACTIVE ),
        ])

        ->add('cfg_mode', SwitchType::class, [
            'label'=>'Mode de synchronisation',
            'label_attr' => ['class' => 'label-mode'],
            'choices' => [
                'Mode basique' => true,
                'Mode complet' => false,
            ],
            // Indice pour l'utilisateur sur ce que fait le mode basique et le mode complet 
            'help' => 'Le mode basique synchronise les stocks, prix et promotions alors que le mode complet tient également les fiches produits à jour.',
            
            'required' => false,
            'data' => ($cfg->get(SyncConfiguration::CFG_WORKMODE) == 0) ? true : false,
        ])

        ->add('title_taskinterval', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Intervalles de synchronisation',
                'help' => 'Nous sommes le '. date('d/m/Y'). ' et il est actuellement ' . date('H:i:s') . ' sur le serveur.',
            ],
        ])

        ->add('sync_product_interval', ChoiceType::class, [
            'label' => 'Synchroniser les produits',
            'choices' => [
                'Dès que possible' => '',
                'Toutes les 10 minutes' => '10min',
                'Toutes les 20 minutes' => '20min',
                'Toutes les 30 minutes' => '30min',
                'Toutes les heures' => '1h',
                'Toutes les 2 heures' => '2h',
                'Toutes les 4 heures' => '4h',
                'Tous les jours' => 'daily',
            ],

            'expanded' => false,
            'required' => false,
            // placeholder false is important to avoid empty option in radio select despite required being false
            'placeholder' => false,
            'column_breaker' => true,
            //'help' => '', // should be set to enable help block
            'help' => 'Dernière synchro. des produits : ' . (isset($lasts_sync['sync_product']) ? 'le '.(new \Datetime($lasts_sync['sync_product']))->format('d/m/Y à H:i:s') : 'jamais'), // should be set to enable help block
            'data' => $cfg->get(SyncConfiguration::CFG_SYNC_PRODUCT_INTERVAL),
        ])

        ->add('sync_stock_interval', ChoiceType::class, [
            'label' => 'Synchroniser le stocks & les prix',
            'choices' => [
                'Dès que possible' => '',
                'Toutes les 10 minutes' => '10min',
                'Toutes les 20 minutes' => '20min',
                'Toutes les 30 minutes' => '30min',
                'Toutes les heures' => '1h',
                'Toutes les 2 heures' => '2h',
                'Toutes les 4 heures' => '4h',
                'Tous les jours' => 'daily',
            ],

            'expanded' => false,
            'required' => false,
            // placeholder false is important to avoid empty option in radio select despite required being false
            'placeholder' => false,
            'column_breaker' => true,
            //'help' => '', // should be set to enable help block
            'help' => 'Dernière synchro. des stocks : ' . (isset($lasts_sync['sync_stock']) ? 'le '.(new \Datetime($lasts_sync['sync_stock']))->format('d/m/Y à H:i:s') : 'jamais'), // should be set to enable help block
            'data' => $cfg->get(SyncConfiguration::CFG_SYNC_STOCK_INTERVAL),
        ])

        ->add('sync_full_product_interval', ChoiceType::class, [
            'label' => 'Resynchroniser totalement les produits',
            'choices' => [                
                'Tous les jours' => 'daily',
                'Toutes les semaines' => 'weekly',
                'Tous les 15 jours' => 'bi-weekly',
                'Tous les mois' => 'monthly',
            ],

            'expanded' => false,
            'required' => false,
            // placeholder false is important to avoid empty option in radio select despite required being false
            'placeholder' => false,
            'column_breaker' => true,
            //'help' => '', // should be set to enable help block
            'help' => 'Dernière resynchro. automatique des produits : ' . (isset($lasts_sync['sync_full_products']) ? 'le '.(new \Datetime($lasts_sync['sync_full_products']))->format('d/m/Y à H:i:s') : 'jamais'), // should be set to enable help block            
            'data' => $cfg->get(SyncConfiguration::CFG_SYNC_FULL_PRODUCT_INTERVAL),
        ])

        ->add('sync_full_stock_interval', ChoiceType::class, [
            'label' => 'Resynchroniser totalement les stocks & les prix',
            'choices' => [
                'Tous les jours' => 'daily',
                'Toutes les semaines' => 'weekly',
                'Tous les 15 jours' => 'bi-weekly',
                'Tous les mois' => 'monthly',
            ],

            'expanded' => false,
            'required' => false,
            // placeholder false is important to avoid empty option in radio select despite required being false
            'placeholder' => false,
            'column_breaker' => true,
            //'help' => '', // should be set to enable help block
            'help' => 'Dernière resynchro. automatique des stocks : ' . (isset($lasts_sync['sync_full_stock']) ? 'le '.(new \Datetime($lasts_sync['sync_full_stock']))->format('d/m/Y à H:i:s') : 'jamais'), // should be set to enable help block
            'data' => $cfg->get(SyncConfiguration::CFG_SYNC_FULL_STOCK_INTERVAL),
        ])
        
        ->add('title_taskcron', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Tâche de synchronisation',
                'help' => '<p>
                                Vous devez configurer une tâche cron qui appelle l\'URL suivante pour lancer la synchronisation automatiquement. <br>
                                Dans un cas standard, cet appel ne devrait pas être plus fréquent que toutes les 5 minutes.
                           </p>
                           <pre class="cron_url">'.$cronUrl.'</pre>
                           <div style="text-align: right;">
                            <button type="button" class="btn btn-secondary btn-sm" onclick="navigator.clipboard.writeText(\''.$cronUrl.'\')">
                                Copier l\'URL dans le presse-papier
                            </button>
                            <a class="btn btn-secondary btn-sm" href="'.$cronUrl.'&details=1" target="_blank"">
                                Ouvrir dans un nouvel onglet
                            </a>
                           </div>
                           <p>
                                Si vous avez accès au serveur, vous pouvez à la place définir une tâche cron qui lance la synchronisation
                                en mode PHP CLI, ce qui est plus sécurisé, fiable et plus rapide que l\'appel HTTP.<br>
                                Dans ce cas, vous n\'avez pas besoin du jetons d\'accès, l\'appel au binaire suffit.
                           </p>
                           <pre class="cron_url">php '.$cliPath.'</pre>
                           ',
            ],
        ])

        ->add('guard_token', TextType::class, [
            'label'=>'Jeton d\'accès',
            // Indice pour l'utilisateur sur ce que fait le mode basique et le mode complet 
            'help' => 'Renseignez ici une chaîne de caractères aléatoires pour sécuriser l\'accès à la tâche de synchronisation. Spécifiez le mot clé "new" pour regénérer un jeton aléatoirement.',
            'required' => false,
            'data' => $guard,
        ])
            
        ->add('title_misc', CustomContentType::class, [
            'label' => false,
            'template' => $this->titleFormTemplatePath,
            'data' => [
                'hr' => true,
                'title' => 'Options diverses',
                'help' => '',
            ],
        ])

        ->add('photo_clean', TextType::class, [
            'label'=>'Nettoyage automatique des photos des produits désactivés (en jours)',
            // Indice pour l'utilisateur sur ce que fait le mode basique et le mode complet 
            'help' => 'Quand cette option > 0, nombre de jours avant lequel les photos des produits désactivés, avec redirection et sans déclinaison sont supprimées du serveur. Permet de faire le ménage automatiquement. Mettre 0 pour désactiver cette fonctionnalité.',
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_PHOTO_CLEAN) ?? 30,
        ])

        ->add('memory_size', TextType::class, [
            'label'=>'Taille mémoire maximale utilisée lors de la synchronisation',
            // Indice pour l'utilisateur sur ce que fait le mode basique et le mode complet
            'help' => 'Définissez la taille maximale de mémoire que la synchronisation peut utiliser. Exemple : 2G pour 2 gigaoctets. Mettre -1 pour pas de limite.',
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_MEMORY_MAX_SIZE) ?? '-1',
        ])

        ->add('api_timeout', TextType::class, [
            'label'=>'Délai d\'attente des appels au backoffice (en secondes)',
            'help' => 'Délai maximal d\'attente d\'une réponse du backoffice lors des appels API (tirage de l\'environnement, synchronisation...). Augmentez cette valeur si vous constatez des erreurs d\'expiration sur de gros volumes. Valeur par défaut : 600.',
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_API_TIMEOUT) ?: 600,
        ])

        ->add('oidc_enabled', SwitchType::class, [
            'label' => 'Autoriser l\'accès maintenance aux équipes de '.$backofficeName,
            'help'  => 'Quand activée, affiche un bouton de connexion pour nos équipes '
                     . 'sur la page de login admin Prestashop pour permettre à nos '
                     . 'techniciens d\'intervenir sur votre site. '
                     . 'Ne désactivez cette option que si '
                     . 'vous comprenez les conséquences (impossibilité pour le '
                     . 'support de se connecter en cas de problème).',
            'required' => false,
            'data' => $cfg->get(SyncConfiguration::CFG_OIDC_ENABLED) !== false,
        ])

        
        ->add('Enregistrer', SubmitType::class, [
            'attr' => ['class' => 'btn-form-valid btn-primary']
        ]);        
        
    }

}