<?php

/**
 * Created by Aurélien RICHAUD (03/01/2017 17:26)
 */

use Myvetshop\Module\Clinique\Checker\PostalCodeChecker;
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;

if (!defined('_PS_VERSION_')) {
    exit;
}

require_once __DIR__ . '/vendor/autoload.php';

require_once __DIR__ . DIRECTORY_SEPARATOR . 'class' . DIRECTORY_SEPARATOR . 'NotificationManager.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'CliniquePush.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'class' . DIRECTORY_SEPARATOR . 'LimitedNumberOfProductByOrder.php';

require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'Animal.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'AnimalSac.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'BuyLimitedNumberOfProducts.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'Cgv.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'CgvCustomer.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'Clinique.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'CliniqueHolidays.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'CustomerPush.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'ExportProduct.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthAccessToken.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthAccessTokenCookie.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthAuthCode.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthClient.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OrderCorrector.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OrderExporter.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OrderSlipExporter.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'Recommandation.php';

require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'MyvetshopVeterinaire.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'MyvetshopCliniqueShipping.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'MyvetshopTheme.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'MyvetshopRecommandationProduct.php';

require_once __DIR__ . DIRECTORY_SEPARATOR . 'Service' . DIRECTORY_SEPARATOR . 'RecommandationManagerApi' . DIRECTORY_SEPARATOR . 'RecommandationController.php';

class MyVetshopClinique extends CarrierModule
{
    const CARRIER_HOME_DEFAULT_PRICE = 'MYVETSHOPCLINIQUE_CARRIER_HOME_DEFAULT_PRICE';
    const PHPLIST_URL = 'MYVETSHOPCLINIQUE_PHPLIST_URL';

    public $id_carrier;

    public function __construct()
    {
        $this->name = 'myvetshopclinique';
        $this->tab = 'administration';
        $this->version = '4.0.4';
        $this->author = 'BtoWeb.fr';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = ['min' => '1.6', 'max' => '1.7'];
        $this->dependencies = ['myvetshoproot'];
        $this->controllers = ['myanimals', 'myanimal', 'myreco'];

        parent::__construct();

        $this->displayName = $this->l('MyVetshop cliniques');
        $this->description = $this->l('Gestion des cliniques / groupes de clients / Livreurs');
        $this->bootstrap = true;

        $this->confirmUninstall = $this->l('Confirmer la désinstallation du plugin ?');

        $this->tabs = [
            [
                'class_name' => 'AdminMyVetShopClinique',
                'visible' => true,
                'name' => 'Cliniques',
                'parent_class_name' => 'AdminMyVetshop',
                'icon' => 'local_hospital',
            ],
            [
                'class_name' => 'AdminMyVetShopVeterinaire',
                'visible' => false,
                'name' => 'Vétérinaires',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueShipping',
                'visible' => false,
                'name' => 'Jours de livraisons',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueHolidays',
                'visible' => false,
                'name' => 'Vacances',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueStatistiques',
                'visible' => true,
                'name' => 'Statistiques',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopExportComptable',
                'visible' => true,
                'name' => 'Exports Comptables',
                'parent_class_name' => 'AdminMyVetshop',
                'icon' => 'account_balance',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueSSOAuthorization',
                'visible' => false,
                'name' => 'SSO Authorization',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueSSOToken',
                'visible' => false,
                'name' => 'SSO Token',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopCliniqueSSOAppToken',
                'visible' => false,
                'name' => 'SSO App Token',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopTheme',
                'visible' => true,
                'name' => 'Thèmes',
                'parent_class_name' => 'AdminMyVetshop',
            ],
            [
                'class_name' => 'AdminMyVetShopAppVetzenMaintenance',
                'visible' => false,
                'name' => 'Maintenance de l\'application vetzen',
                'parent_class_name' => 'AdminMyVetshop',
            ],
        ];
    }

    public function getOrderShippingCost($parameters, $shipping_cost)
    {
        return $this->getOrderShippingCostExternal($parameters);
    }

    /**
     * @param Cart $cart
     *
     * @return false|mixed
     */
    public function getOrderShippingCostExternal($cart)
    {
        $carrier = new Carrier($this->id_carrier);
        $ranges = Carrier::getDeliveryPriceByRanges($carrier->getRangeTable(), $carrier->id);
        $range = end($ranges);

        //Si on a pas de range, alors le transporteur n'est pas bon et on le masque.
        if (!array_key_exists('price', $range)) {
            return false;
        }

        $address = new Address($cart->id_address_delivery);

        //Si le code postal n'est pas autorisé, alors on masque le transporteur
        if ('France' == $address->country && !PostalCodeChecker::canDelivery($address->postcode)) {
            return false;
        }

        return $range['price'];
    }

    public function getContent()
    {
        $this->postProcess();

        return $this->renderForm();
    }

    public function hookModuleRoutes()
    {
        return [
            'module-myvetshopclinique-myanimals' => [
                'controller' => 'myanimals',
                'rule' => 'myanimals',
                'keywords' => [],
                'params' => [
                    'module' => $this->name,
                    'fc' => 'module',
                ],
            ],
            'module-myvetshopclinique-myreco' => [
                'controller' => 'myreco',
                'rule' => 'myreco',
                'keywords' => [],
                'params' => [
                    'module' => $this->name,
                    'fc' => 'module',
                ],
            ],
        ];
    }

    public function hookActionObjectCustomerAddAfter($params)
    {
        /** @var Customer $object */
        $object = $params['object'];

        $this->syncCustomerWithPhpList($object);
    }

    public function hookActionObjectCustomerUpdateAfter(array $params): void
    {
        /** @var Customer $object */
        $object = $params['object'];

        $this->syncCustomerWithPhpList($object);
    }

    /**
     * On ajoute le champ "Code privilège" dans le formulaire de création/modification de compte client
     *
     * @param array $parameters
     *
     * @return array
     */
    public function hookAdditionalCustomerFormFields(array $parameters): array
    {
        $field = (new FormField())
            ->setName('code_privilege')
            ->setType('text')
            ->setLabel(
                $this->trans(
                    'Code privilège',
                    [],
                    'Modules.myvetshopclinique.Shop'
                )
            )
            ->setRequired(true);

        if ($this->context->customer->isLogged()) {
            $clinique = Clinique::getCliniqueByGroupId((int) $this->context->customer->id_default_group);

            if (!is_null($clinique)) {
                $group = new Group($this->context->customer->id_default_group, Context::getContext()->language->id);
                $field->setValue($group->name);
            }
        }

        $fields = ['code_privilege' => $field];

        if (isset($parameters['fields']['optin']) && $parameters['fields']['optin'] instanceof FormField) {
            // TODO : Utiliser le système de traduction
            $parameters['fields']['optin']->setLabel("Recevez des informations & conseils personnalisés pour votre animal, qualifiés par l'équipe de docteurs vétérinaires MyVetshop ! (environ 1 email / mois)");
        }

        if (isset($parameters['fields']['newsletter']) && $parameters['fields']['newsletter'] instanceof FormField) {
            // TODO : Utiliser le système de traduction
            $parameters['fields']['newsletter']->setLabel('Recevez les informations importantes de votre clinique (fermeture exceptionnelle...) et du site MyVetshop ! (environ 4 emails / an)');
        }

        return $fields;
    }

    public function hookDisplayCustomerAccountForm(): ?string
    {
        if (Tools::getIsset('create_account')) {
            $fields = [];

            $addressForm = $this->getCustomerAddressForm();

            //Si et seulement si on a lancé le formulaire, alors on check les champs
            //Sinon on aura des erreurs d'affichés la première fois qu'on arrive sur le formulaire
            if (Tools::getIsset('submitCreate')) {
                $addressForm->validate();
            }

            foreach ($addressForm->getFormatter()->getFormat() as $fieldName => $row) {
                $fields = array_merge($fields, [$addressForm->getField($fieldName)]);
            }

            $fields = array_map(
                function (FormField $field) {
                    return $field->toArray();
                },
                $fields
            );

            $this->context->smarty->assign('addressFormFields', $fields);

            return $this->fetch('module:myvetshopclinique/views/templates/hook/hook_display_customer_account_form.tpl');
        }

        return null;
    }

    public function hookValidateCustomerFormFields(array $parameters): array
    {
        /**
         * @var FormField[]
         */
        $fields = $parameters['fields'];

        foreach ($fields as $field) {
            if ('code_privilege' == $field->getName()) {
                $code = Tools::getValue($field->getName());

                if (!empty($code)) {
                    $clinique = Clinique::getByCodePrivilege($code);

                    if (is_null($clinique) || $clinique->isCliniqueTest()) {
                        $field->addError($this->trans('Code privilège invalide'));
                    }
                }
            }
        }

        if (Tools::getIsset('create_account')) {
            //On est obligé de faire comme dans hookDisplayCustomerAccountForm pour que le formulaire détecte si il y a eu une erreur dans le formulaire de l'adresse
            $addressForm = $this->getCustomerAddressForm();
            $addressForm->validate();

            foreach ($addressForm->getFormatter()->getFormat() as $fieldName => $row) {
                $fields = array_merge($fields, [$addressForm->getField($fieldName)]);
            }
        }

        return $fields;
    }

    /**
     * @param array<string, mixed> $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionCustomerAccountAdd(array $params): void
    {
        /** @var Customer $customer */
        $customer = $params['newCustomer'];
        $codePrivilege = Tools::getValue('code_privilege');

        $clinique = Clinique::getByCodePrivilege($codePrivilege);

        if (!is_null($clinique) && !$clinique->isCliniqueTest()) {
            if ('-PRO' === substr(strtoupper($codePrivilege), -4)) {
                $groupDefaultId = $clinique->getGroupRural()->id;
            } else {
                $groupDefaultId = $clinique->getGroupDefault()->id;
            }

            // On ajoute l'utilisateur au groupe de la clinique
            $customer->updateGroup([3, $groupDefaultId]);

            //On définit le groupe de la clinique comme groupe par défaut
            $customer->id_default_group = $groupDefaultId;
            $customer->save();
        }

        if (Tools::getIsset('submitCreate')) {
            $addressForm = $this->getCustomerAddressForm();
            $addressForm->submit();
        }
    }

    /**
     * @param array<string, mixed> $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionCustomerAccountUpdate(array $parameters): void
    {
        $parameters['newCustomer'] = $parameters['customer'];

        $this->hookActionCustomerAccountAdd($parameters);
    }

    public function hookActionOrderStatusUpdate(array $params): void
    {
        /** @var OrderState $newOrderStatus */
        $newOrderStatus = $params['newOrderStatus'];
        $order = new Order($params['id_order']);

        try {
            $notificationManager = new NotificationManager();

            $result = Db::getInstance()
                ->executeS('SELECT * FROM `ps_customer_push` WHERE `id_customer` = ' . (int) $order->id_customer);

            if (!is_array($result)) {
                $result = [];
            }

            /** @var CustomerPush[] $customerPushes */
            $customerPushes = ObjectModel::hydrateCollection(
                CustomerPush::class, $result
            );

            $message = null;
            switch ($newOrderStatus->template) {
                case 'preparation':
                    $message = 'Votre commande ' . $order->reference . ' est en cours de préparation';
                    break;

                case 'shipped':
                    $message = 'Votre commande ' . $order->reference . ' est expédiée';
                    break;

                case 'order_clinique':
                    $message = 'Votre commande ' . $order->reference . " est disponible à la clinique. Merci de suivre les mesures de distanciation sociale qui s'imposent.";
                    break;

                default:
                    // Rien
            }

            if ($message) {
                $nb_telephones_destination = 0;

                foreach ($customerPushes as $customerPush) {
                    try {
                        $notificationManager->sendNotification($customerPush, $message);
                        ++$nb_telephones_destination;
                    } catch (\GuzzleHttp\Exception\GuzzleException $e) {
                        // Inhibiteur d'erreur
                        //var_dump($e);
                    } catch (Exception $exception) {
                        // Inhibiteur d'erreur
                        //var_dump($exception);
                    }
                }

                // Ajout d'une note dans la commande pour indiquer qu'elle vient de l'application mobile
                $msg = new Message();
                $message_prive = strip_tags("Notification envoyée sur l'application mobile (" . $nb_telephones_destination . ' terminaux) : ' . $message, '<br>');
                if (Validate::isCleanHtml($message_prive)) {
                    $msg->message = $message_prive;
                    $msg->id_cart = (int) $order->id_cart;
                    $msg->id_customer = (int) ($order->id_customer);
                    $msg->id_order = (int) $order->id;
                    $msg->private = true;
                    try {
                        $msg->add();
                    } catch (PrestaShopDatabaseException $e) {
                        // Inhibiteur d'erreur
                    } catch (PrestaShopException $e) {
                        // Inhibiteur d'erreur
                    }
                }
            }
        } catch (Exception $exception) {
            // Inhibiteur d'erreur
            //var_dump($exception);
        }
    }

    public function hookCustomerAccount(array $parameters): string
    {
        return $this->fetch('module:myvetshopclinique/views/templates/hook/hook_customer_account.tpl');
    }

    //@TODO MIGRATION 17 A supprimer ?
    public function hookHideOrShowStatMenu(array $params): void
    {
        $smarty = $params['smarty'];

        if (isset($params['module'])) {
            $params['module']['class'] = '';

            $cookieContent = Context::getContext()->cookie->getAll();
            if (isset($cookieContent['profile'])) {
                $resultat = Db::getInstance()->executeS(
                    '
                    SELECT m.name, ma.view
                    FROM `' . _DB_PREFIX_ . 'module` m
                    LEFT JOIN `' . _DB_PREFIX_ . 'module_access` ma ON ma.id_module = m.id_module AND ma.id_profile = ' . (int) $cookieContent['profile'] . '
                    WHERE m.name = "' . Db::getInstance()->escape($params['module']['name']) . '"
                '
                );

                if (is_array($resultat) && count($resultat) && isset($resultat[0]['view']) && 0 == $resultat[0]['view']) {
                    $params['module']['class'] = ' hidden';
                }
            }

            $smarty->assign('module_class', $params['module']['class']);
        }
    }

    //@TODO MIGRATION 17
    public function hookMyvetshopHoliday(array $params): void
    {
        $smarty = $params['smarty'];

        $context = Context::getContext();
        $group = (int) $context->customer->id_default_group;

        $holiday = Db::getInstance()->getRow(
            'SELECT mch.*, (CURDATE() BETWEEN mch.date_debut AND mch.date_fin) AS block_paiement FROM `' . _DB_PREFIX_ . 'myvetshop_clinique` mc
                        INNER JOIN `' . _DB_PREFIX_ . 'myvetshop_clinique_holidays` mch ON mch.id_myvetshop_clinique = mc.id_myvetshop_clinique 
                        WHERE mc.id_group = ' . $group . ' AND (
                            CURDATE() BETWEEN mch.date_debut AND mch.date_fin
                            OR
                            CURDATE() BETWEEN mch.date_alerte AND mch.date_debut
                        )'
        );

        if ($holiday) {
            // Laisse le paiement de la commande
            $smarty->assign('allow_paiement', '1');
            //$smarty->assign('allow_paiement', $holiday['block_paiement'] ? '0' : '1');
            $smarty->assign('myvetshop_holiday_message', $holiday['block_paiement'] ? $holiday['message'] : $holiday['message_alerte']);
        }
    }

    //@TODO MIGRATION 17
    public function hookMyvetshopMessageClinique(array $params): void
    {
        try {
            $smarty = $params['smarty'];

            $context = Context::getContext();
            $group_id = (int) $context->customer->id_default_group;

            $clinique_id = Clinique::getCliniqueIdByGroup((int) $group_id);

            if ($clinique_id) {
                $clinique = new Clinique($clinique_id);
                $smarty->assign('myvetshop_message_clinique', $clinique->message);
            }
        } catch (PrestaShopDatabaseException $e) {
        } catch (PrestaShopException $e) {
        }
    }

    //@TODO MIGRATION 17
    public function hookActionAdminControllerSetMedia(array $params): void
    {
        //if ($this->context->controller->controller_name == 'YourAdminController'
        $this->context->controller->addCSS($this->_path . 'css/admin.css');
    }

    /**
     * Personnalisation plus avancée des e-mails
     *
     * @param array<string, mixed> $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionGetExtraMailTemplateVars(array $params): void
    {
        // Uniquement pour le e-mails "shipped" (lors de l'envoi du colis)
        if (!isset($params['template'])
            || !isset($params['template_vars'])
            || !in_array($params['template'], ['shipped', 'order_clinique'])
            || !isset($params['extra_template_vars'])
            || !isset($params['template_vars']['{id_order}'])) {
            return;
        }

        // Récupération de la commande
        $order = new Order($params['template_vars']['{id_order}']);
        if (!$order->id_carrier) {
            return;
        }

        require_once __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'Clinique.php';

        $id_clinique = Clinique::getCliniqueIdByCarrier((int) $order->id_carrier);
        if (!$id_clinique) {
            return;
        }

        // Chargement des informations
        $clinique = new Clinique($id_clinique);
        $store = new Store($clinique->id_store, Context::getContext()->language->id);

        /////////////////////////////////////////
        /// Génération du texte l'e-mail
        $order_html = '';
        switch (Clinique::getCarrierType((int) $order->id_carrier)) {
            case Clinique::CARRIER_CLINIQUE:
                switch ($params['template']) {
                    case 'order_clinique':
                        $order_html
                            = '<strong>ATTENTION : </strong> Compte tenu de la situation face au coronavirus, nous vous invitons à prendre contact directement avec votre propre clinique vétérinaire. Vous serez assurés de connaître ses nouveaux horaires d’ouvertures et protocoles pour récupérer vos commandes au mieux. Attention les horaires ci-dessous sont susceptibles de changer :';
                        //$order_html = "Votre clinique <strong>" . $store->name . "</strong> est ouverte aux horaires suivants :";
                        break;

                    default:
                        $order_html
                            = '<strong>ATTENTION : </strong> Compte tenu de la situation face au coronavirus, nous vous invitons à prendre contact directement avec votre propre clinique vétérinaire. Vous serez assurés de connaître ses nouveaux horaires d’ouvertures et protocoles pour récupérer vos commandes au mieux. Attention les horaires ci-dessous sont susceptibles de changer :';
                    //$order_html = "Elle sera disponible dans votre clinique vétérinaire entre 2j et 4j ouvrés après réception de ce message aux horaires suivants :";
                }
                $order_html .= "<br /><br/>\n";
                // Récupèrse les heures d'ouverture en fonction des jours
                $hours = json_decode($store->getWsHours(), true);

                if (!is_array($hours) || count($hours) > 7) {
                    $horaires_html = 'Horaires non disponibles';
                } else {
                    $jours = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche'];
                    $horaires_html = '';

                    // Génération
                    foreach ($hours as $i => $horaires) {
                        if (6 == $i) {
                            // Ignore le dimanche
                            continue;
                        }
                        $horaires_html .= $jours[$i] . ' : ' . (isset($horaires[0]) && $horaires[0] ? $horaires[0] : 'Non renseigné') . "<br>\n";
                    }
                }

                $order_html .= $horaires_html;

                switch ($params['template']) {
                    case 'order_clinique':
                        $order_html .= '<br />'
                            . "A l'adresse suivante :<br />" . $store->address1 . '<br />' . ($store->address2 ? $store->address2 . '<br />' : '') . $store->postcode . ' ' . $store->city . '<br />';
                        break;

                    default:
                }
                break;

            case Clinique::CARRIER_DOMICILE:
                $order_html = "Elle sera livrée directement à l'adresse de livraison que vous avez indiqué :<br/>\n";
                $address_delivery = new Address($order->id_address_delivery);

                $order_html .= $address_delivery->firstname . ' ' . $address_delivery->lastname . ($address_delivery->company ? ' (' . $address_delivery->company . ')' : '') . "<br>\n";
                $order_html .= $address_delivery->address1 . "<br>\n";
                if ($address_delivery->address2) {
                    $order_html .= $address_delivery->address2 . "<br>\n";
                }
                $order_html .= $address_delivery->postcode . ' ' . $address_delivery->city . ' ' . $address_delivery->country . "<br>\n";
                break;

            case Clinique::CARRIER_INCONNU:
                $order_html = "Elle sera livrée suivant les modalités que vous avez choisi lors du passage de commande :<br/>\n";
                $order_html .= (new Carrier($order->id_carrier, Context::getContext()->language->id))->name;
                break;
        }

        $params['extra_template_vars']['{order_html}'] = $order_html;
        $params['extra_template_vars']['{order_text}'] = strip_tags($order_html);
    }

    public function hookDisplayHeader(): void
    {
        $mobile_app_flag = Tools::getValue('mobile_app');

        // Gestion automatique du mode "application mobile"
        if (!is_null($mobile_app_flag) && is_numeric($mobile_app_flag)) {
            if (1 === intval($mobile_app_flag)) {
                $this->context->cookie->mobile_app = 1;
            } else {
                unset($this->context->cookie->mobile_app);
            }
            $this->context->cookie->write();
        }

        if ($this->context->cookie->mobile_app) {
            $this->context->controller->registerStylesheet('mvs-clinique-mobileapp-css', $this->_path . 'css/mobileapp.css');
            $this->context->controller->registerJavascript('mvs-clinique-mobileapp-js', $this->_path . 'js/mobileapp.js');
            $this->context->smarty->assign('mobileapp', true);
        }

        if (class_exists('MyvetshopcliniqueMyRecoModuleFrontController') && $this->context->controller instanceof MyvetshopcliniqueMyRecoModuleFrontController) {
            $this->context->controller->registerStylesheet('mvs-clinique-myreco-css', $this->_path . 'css/my_reco.css');
            $this->context->controller->registerStylesheet('mvs-clinique-myreco-add-css', $this->_path . 'css/my_reco_add.css');
            $this->context->controller->registerStylesheet('mvs-clinique-myreco-public-css', $this->_path . 'css/my_reco_public.css');
        }

        // Injection de la clinique
        if ($this->context->customer->isLogged()) {
            $clinic = Clinique::getCliniqueByGroupId($this->context->customer->id_default_group);

            if ($clinic) {
                $this->context->smarty->assign('clinic', Clinique::getCliniqueByGroupId($this->context->customer->id_default_group));
                $store = new Store($clinic->id_store, $this->context->language->id);
                $this->context->smarty->assign('clinic_store', $store);
                $storeHours = json_decode($store->getWsHours(), true);
                $currentDay = (intval(date('w')) + 6) % 7;
                $todayHours = $storeHours[$currentDay] ?? ['Horaires non disponibles'];
                $this->context->smarty->assign('clinic_store_hour', $todayHours[0]);

                // Photo de la clinique
                $photo_path = _PS_STORE_IMG_DIR_ . $clinic->id_store . '.jpg';
                if (!is_file($photo_path)) {
                    $photo_path = _PS_MODULE_DIR_ . 'myvetshopclinique/img/clinique-photo-par-defaut@1x.png';
                }
                $photo_path = str_replace(_PS_ROOT_DIR_, '', $photo_path);
                $photo_url = Tools::getCurrentUrlProtocolPrefix() . Tools::getMediaServer($photo_path) . $photo_path;
                $this->context->smarty->assign('clinic_photo', $photo_url);

                // Logo de la clinique
                $logo_path = _PS_EMPLOYEE_IMG_DIR_ . $clinic->id_employee . '.jpg';
                if (!is_file($logo_path)) {
                    $logo_path = _PS_MODULE_DIR_ . 'myvetshopclinique/img/clinique-logo-par-defaut@1x.png';
                }
                $logo_path = str_replace(_PS_ROOT_DIR_, '', $logo_path);
                $logo_url = Tools::getCurrentUrlProtocolPrefix() . Tools::getMediaServer($logo_path) . $logo_path;
                $this->context->smarty->assign('clinic_logo', $logo_url);
            }

            // Récupération de la date de dernière commande
            $idLastOrder = Db::getInstance(_PS_USE_SQL_SLAVE_)
                ->getValue(
                    'SELECT `o`.`id_order`'
                    . ' FROM `' . _DB_PREFIX_ . 'orders` o'
                    . ' INNER JOIN `' . _DB_PREFIX_ . 'order_state` os ON `os`.`id_order_state` = `o`.`current_state`'
                    . ' WHERE `o`.`id_customer` = ' . (int) $this->context->customer->id
                    . ' AND `os`.`paid` = 1'
                    . ' ORDER BY `o`.`date_add` DESC'
                );

            if ($idLastOrder) {
                $lastOrder = new Order($idLastOrder);
                $this->context->smarty->assign('last_order', $lastOrder);
                $lastCarrier = Carrier::getCarrierByReference($lastOrder->id_carrier, $this->context->language->id);
                $this->context->smarty->assign('last_carrier', $lastCarrier);
            } else {
                $this->context->smarty->assign('last_order', null);
                $this->context->smarty->assign('last_carrier', null);
            }
        }
    }

    /**
     * @param array<string, mixed> $params
     */
    public function hookActionBeforeCartUpdateQty(array $params): void
    {
        $operator = $params['operator'];

        if ('up' === $operator) {
            /** @var Cart $cart */
            $cart = $params['cart'];

            /** @var Product $product */
            $product = $params['product'];

            if (!LimitedNumberOfProductByOrder::canBuyProduct($cart, $product, (int) $params['quantity'])) {
                $product->available_for_order = false;
            }
        }
    }

    /**
     * @param array<string, mixed> $params
     */
    public function hookDisplayAddRecoLink(array $params): string
    {
        return $this->display(__FILE__, 'add_reco.tpl');
    }

    public function hookActionObjectMyvetshopThemeAddAfter(array $parameters): void
    {
        $this->hookActionObjectMyvetshopThemeUpdateAfter($parameters);
    }

    public function hookActionObjectMyvetshopThemeUpdateAfter(array $parameters): void
    {
        /**
         * @var MyvetshopTheme $theme
         */
        $theme = $parameters['object'];
        $themePathDirectory = $this->getLocalPath() . '/css/theme';
        $coreCssPath = $themePathDirectory . '/core.css';

        if (file_exists($coreCssPath)) {
            $css = file_get_contents($coreCssPath);

            $css = str_replace('$color_1', $theme->color_1, $css);
            $css = str_replace('$color_2', $theme->color_2, $css);
            $css = str_replace('$color_3', $theme->color_3, $css);
            $css = str_replace('$color_4', $theme->color_4, $css);
            $css = str_replace('$color_5', $theme->color_5, $css);

            $themeBuildDirectory = $themePathDirectory . '/build';

            if (!file_exists($themeBuildDirectory)) {
                mkdir($themeBuildDirectory);
            }

            file_put_contents($themeBuildDirectory . '/' . $theme->getFilename(), $css);
        }
    }

    public function hookActionFrontControllerSetMedia(): void
    {
        $themeId = (int) Tools::getValue('theme_privilege', $this->context->cookie->theme_privilege);
        $theme = new MyvetshopTheme($themeId);

        if (Validate::isLoadedObject($theme)) {
            if (file_exists($this->getLocalPath() . '/css/theme/build/' . $theme->getFilename())) {
                $this->context->controller->registerStylesheet('myvetshop-theme-' . $theme->id, $this->getPathUri() . '/css/theme/build/' . $theme->getFilename(), ['priority' => 25]);
            }
        }
    }

    public function hookActionControllerInitAfter(array $parameters): void
    {
        if ($this->context && isset($this->context->customer->id_default_group) && $this->context->customer->id_default_group > 3) {
            if (!isset($this->context->cookie->id_clinique) || !$this->context->cookie->id_clinique) {
                $clinique = Clinique::getCliniqueByGroupId((int) $this->context->customer->id_default_group);

                if ($clinique) {
                    $this->context->cookie->id_clinique = $clinique->id;
                    $this->context->cookie->theme_privilege = $clinique->hasTheme() ? $clinique->getTheme()->id : null;
                } else {
                    unset($this->context->cookie->theme_privilege);
                    unset($this->context->cookie->id_clinique);
                }
            }
        }
    }

    public function hookActionCustomerLogoutAfter()
    {
        unset($this->context->cookie->theme_privilege);
        unset($this->context->cookie->id_clinique);
    }

    public function hookDisplayBeforeCarrier(): ?string
    {
        return null;
    }

    public function hookDisplayCarrierExtraContent($parameters): string
    {
        $carrierId = $parameters['carrier']['id'];
        $carrier = new Carrier($carrierId);

        //Si le transporteur est gratuit, on considèreque c'est "En clinique"
        if ($carrier->is_free) {
            $clinique = Clinique::getCliniqueByCarrierId($carrierId);

            if (!is_null($clinique)) {
                $this->context->smarty->assign('store', $clinique->getStore($this->context->language->id));

                return $this->fetch('module:myvetshopclinique/views/templates/hook/hook_display_carrier_extra_content.tpl');
            }
        }

        return '';
    }

    public function hookActionAddressGridQueryBuilderModifier(array $parameters): void
    {
        $cookieParameters = Context::getContext()->cookie->getAll();

        if (isset($cookieParameters['profile']) && 5 == $cookieParameters['profile']) {
            $employeeId = (int) $cookieParameters['id_employee'];

            $clinique = Clinique::getCliniqueByEmployeeId($employeeId);
            $groupId = !is_null($clinique) ? $clinique->id_group : 0;

            /**
             * @var \Doctrine\DBAL\Query\QueryBuilder $searchQueryBuilder
             */
            $searchQueryBuilder = $parameters['search_query_builder'];
            $searchQueryBuilder->innerJoin('customer', _DB_PREFIX_ . 'customer_group', 'customer_group', 'customer.id_customer=customer_group.id_customer AND customer_group.id_group=' . $groupId);

            /**
             * @var \Doctrine\DBAL\Query\QueryBuilder $countQueryBuilder
             */
            $countQueryBuilder = $parameters['count_query_builder'];
            $countQueryBuilder->innerJoin('customer', _DB_PREFIX_ . 'customer_group', 'customer_group', 'customer.id_customer=customer_group.id_customer AND customer_group.id_group=' . $groupId);
        }
    }

    public function hookActionAdminCartsListingFieldsModifier(array $parameters): void
    {
        $cookieParameters = Context::getContext()->cookie->getAll();

        if (isset($cookieParameters['profile']) && 5 == $cookieParameters['profile']) {
            $employeeId = (int) $cookieParameters['id_employee'];

            $clinique = Clinique::getCliniqueByEmployeeId($employeeId);
            $groupId = !is_null($clinique) ? $clinique->id_group : 0;

            $parameters['join'] .= ' INNER JOIN ' . _DB_PREFIX_ . 'customer_group customer_group ON c.id_customer=customer_group.id_customer AND customer_group.id_group=' . $groupId;
        }
    }

    public function hookActionCustomerGridQueryBuilderModifier(array $parameters): void
    {
        $this->hookActionAddressGridQueryBuilderModifier($parameters);

        /**
         * @var \Doctrine\DBAL\Query\QueryBuilder $searchQueryBuilder
         */
        $searchQueryBuilder = $parameters['search_query_builder'];

        $searchQueryBuilder
            ->addSelect('group_lang.name as code_privilege')
            ->leftJoin('c', _DB_PREFIX_ . Group::$definition['table'] . '_lang', 'group_lang', 'c.id_default_group=group_lang.id_group AND group_lang.id_lang=:context_lang_id AND c.id_default_group > 3');
    }

    public function hookActionCustomerGridDefinitionModifier(array $parameters): void
    {
        /**
         * @var \PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface $definition
         */
        $definition = $parameters['definition'];

        /**
         * @var \PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection $columns
         */
        $columns = $definition->getColumns();

        $columns
            ->addAfter('email',
                (new DataColumn('code_privilege'))
                    ->setName($this->trans('Code Privilège', [], 'Modules.Myvetshopclinique.Admin'))
                    ->setOptions(['field' => 'code_privilege', 'clickable' => false])
            );
    }

    public function hookActionAdminControllerInitBefore()
    {
        if ($this->context->controller instanceof AdminDashboardController && 5 == $this->context->employee->id_profile) {
            Tools::redirectAdmin($this->context->link->getAdminLink('AdminMyVetShopClinique'));
        }
    }

    public function getCarrierHomeDefaultPrice(): int
    {
        return (int) Configuration::get(self::CARRIER_HOME_DEFAULT_PRICE, null, null, null, 14);
    }

    public function getPhpListDefaultValue(): string
    {
        return (string) Configuration::get(self::PHPLIST_URL, null, null, null, '');
    }

    public function install(): bool
    {
        $result = parent::install()
            && $this->installTables()
            && $this->registerHook('actionObjectCustomerAddAfter')
            && $this->registerHook('actionObjectCustomerUpdateAfter')
            && $this->registerHook('actionCustomerUpdate')
            && $this->registerHook('actionCustomerAccountAdd')
            && $this->registerHook('actionCustomerAccountUpdate')
            && $this->registerHook('actionOrderStatusUpdate')
            && $this->registerHook('customerAccount')
            && $this->registerHook('hideOrShowStatMenu')
            && $this->registerHook('myvetshopHoliday')
            && $this->registerHook('myvetshopMessageClinique')
            && $this->registerHook('actionAdminControllerSetMedia')
            && $this->registerHook('actionGetExtraMailTemplateVars')
            && $this->registerHook('displayHeader')
            && $this->registerHook('displayAddRecoLink')
            && $this->registerHook('actionFrontControllerSetMedia')
            && $this->registerHook('actionBeforeCartUpdateQty')
            && $this->registerHook('actionObjectMyvetshopThemeAddAfter')
            && $this->registerHook('actionObjectMyvetshopThemeUpdateAfter')
            && $this->registerHook('actionControllerInitAfter')
            && $this->registerHook('actionCustomerLogoutAfter')
            && $this->registerHook('additionalCustomerFormFields')
            && $this->registerHook('displayCustomerAccountForm')
            && $this->registerHook('validateCustomerFormFields')
            && $this->registerHook('displayBeforeCarrier')
            && $this->registerHook('displayCarrierExtraContent')
            && $this->registerHook('moduleRoutes')
            && $this->registerHook('actionAddressGridQueryBuilderModifier')
            && $this->registerHook('actionAdminCartsListingFieldsModifier')
            && $this->registerHook('actionCustomerGridQueryBuilderModifier')
            && $this->registerHook('actionCustomerGridDefinitionModifier')
            && $this->registerHook('actionAdminControllerInitBefore');

        return $result;
    }

    protected function postProcess(): void
    {
        if (Tools::isSubmit('submitOptionsSettings')) {
            Configuration::updateValue(static::CARRIER_HOME_DEFAULT_PRICE, Tools::getValue(self::CARRIER_HOME_DEFAULT_PRICE));
            Configuration::updateValue(static::PHPLIST_URL, Tools::getValue(self::PHPLIST_URL));
        }
    }

    protected function renderForm()
    {
        $langId = $this->context->language->id;

        $fields_form = [
            'form' => [
                'legend' => [
                    'title' => $this->l('Settings'),
                    'icon' => 'icon-cogs',
                ],
                'input' => [
                    [
                        'name' => static::CARRIER_HOME_DEFAULT_PRICE,
                        'label' => $this->l('Tarif de livraison à domicile par défaut (H.T)'),
                        'type' => 'text',
                    ],
                    [
                        'name' => static::PHPLIST_URL,
                        'label' => $this->l('URL PHPList'),
                        'type' => 'text',
                        'placeholder' => 'https://newsletter.myvetshop.fr (laisser blanc pour désactiver)',
                    ],
                ],
                'submit' => [
                    'title' => $this->l('Save'),
                ],
            ],
        ];

        $helper = new HelperForm();
        $helper->show_toolbar = false;
        $helper->table = $this->table;
        $helper->default_form_language = $langId;
        $helper->module = $this;
        $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0;
        $helper->identifier = $this->identifier;
        $helper->submit_action = 'submitOptionsSettings';
        $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false) . '&configure=' . $this->name . '&tab_module=' . $this->tab . '&module_name=' . $this->name;
        $helper->token = Tools::getAdminTokenLite('AdminModules');
        $helper->tpl_vars = [
            'uri' => $this->getPathUri(),
            'fields_value' => $this->getFieldsValues(),
            'languages' => $this->context->controller->getLanguages(),
            'id_language' => $this->context->language->id,
        ];

        return $helper->generateForm([$fields_form]);
    }

    protected function getFieldsValues()
    {
        return [
            static::CARRIER_HOME_DEFAULT_PRICE => Tools::getValue(static::CARRIER_HOME_DEFAULT_PRICE, $this->getCarrierHomeDefaultPrice()),
            static::PHPLIST_URL => Tools::getValue(static::PHPLIST_URL, $this->getPhpListDefaultValue()),
        ];
    }

    protected function getCustomerAddressForm(): CustomerAddressFormCore
    {
        if (Configuration::get('PS_RESTRICT_DELIVERED_COUNTRIES')) {
            $availableCountries = Carrier::getDeliveredCountries($this->context->language->id, true, true);
        } else {
            $availableCountries = Country::getCountries($this->context->language->id, true);
        }

        $addressPersister = new CustomerAddressPersister(
            $this->context->customer,
            $this->context->cart,
            ''
        );

        $addressFormatter = new CustomerAddressFormatter(
            $this->context->country,
            $this->getTranslator(),
            $availableCountries
        );

        $addressForm = new CustomerAddressForm(
            $this->context->smarty,
            $this->context->language,
            $this->getTranslator(), $addressPersister, $addressFormatter);

        $addressForm->fillWith(Tools::getAllValues());

        return $addressForm;
    }

    protected function installTables(): bool
    {
        return Clinique::install()
            && MyvetshopCliniqueShipping::install()
            && CliniqueHolidays::install()
            && CliniquePush::install()
            && OAuthClient::install()
            && OAuthAuthCode::install()
            && OAuthAccessToken::install()
            && ExportProduct::install()
            && Recommandation::install()
            && BuyLimitedNumberOfProducts::install()
            && MyvetshopVeterinaire::install()
            && MyvetshopTheme::install()
            && MyvetshopRecommandationProduct::install();
    }

    /**
     * @param Customer $customer
     */
    public function syncCustomerWithPhpList(Customer $customer): void
    {
        $phplistUrl = Configuration::get(self::PHPLIST_URL);

        if (!$phplistUrl) {
            return;
        }

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $phplistUrl . '/lists/?pi=myvetshop&p=syncfromprestashop');
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt(
            $curl, CURLOPT_POSTFIELDS, [
                'email' => $customer->email,
                'newsletter' => $customer->newsletter,
                'optin' => $customer->optin,
                'firstname' => $customer->firstname,
                'lastname' => $customer->lastname,
            ]
        );
        curl_exec($curl);
    }
}
