<?php

namespace PrestaShop\Module\PolarisPrestaConnector\Forms;

use PrestaShop\Module\PolarisPrestaConnector\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('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']
        ]);        
        
    }

}