<?php

declare(strict_types=1);

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

use Myvetshop\Module\Clinique\Checker\PostalCodeChecker;
use Myvetshop\Module\Clinique\Clinic\ClinicEmailRedirectionManager;
use Myvetshop\Module\Clinique\Stock\CentravetStockApi;
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;

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

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 . 'Clinique.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'CliniqueHolidays.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'CliniquePush.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'CustomerPush.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'EstablishmentEvent.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 . 'OrderSlipExporter.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'Recommandation.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'classes' . \DIRECTORY_SEPARATOR . 'NoOpCache.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 . 'class' . \DIRECTORY_SEPARATOR . 'NotificationManager.php';
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'class' . \DIRECTORY_SEPARATOR . 'LimitedNumberOfProductByOrder.php';

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

class myvetshopclinique extends CarrierModule
{
    public const CARRIER_HOME_DEFAULT_PRICE = 'MYVETSHOPCLINIQUE_CARRIER_HOME_DEFAULT_PRICE';
    public const PHPLIST_URL = 'MYVETSHOPCLINIQUE_PHPLIST_URL';
    public const CENTRAVET_API_URL = 'MYVETSHOPCLINIQUE_CENTRAVET_API_URL';
    public const CENTRAVET_API_USER = 'MYVETSHOPCLINIQUE_CENTRAVET_API_USER';
    public const CENTRAVET_API_PASS = 'MYVETSHOPCLINIQUE_CENTRAVET_API_PASS';

    public ?int $id_carrier = null;

    protected function generateControllerURI(): string
    {
        $container = SymfonyContainer::getInstance();
        if ($container) {
            /** @var \Symfony\Component\Routing\RouterInterface $router */
            $router = $container->get('router');

            return $router->generate('accounting_export');
        }

        return '';
    }

    public function __construct()
    {
        $this->name = 'myvetshopclinique';
        $this->tab = 'administration';
        $this->version = '4.2.22';
        $this->author = 'BtoWeb.fr';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = ['min' => '1.7.8.9', 'max' => '1.7.8.99'];
        $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',
                'route_name' => 'accounting_export',
                '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',
            ],
        ];
    }

    /**
     * @param Cart $parameters
     * @param mixed $shipping_cost
     *
     * @return false|string
     */
    public function getOrderShippingCost($parameters, $shipping_cost)
    {
        return $this->getOrderShippingCostExternal($parameters);
    }

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

        // Si on n'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(): string
    {
        $this->postProcess();

        return $this->renderForm();
    }

    /**
     * @return array<string, mixed>
     */
    public function hookModuleRoutes(): array
    {
        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',
                ],
            ],
        ];
    }

    /**
     * @param array{object: Clinique} $params
     */
    public function hookActionObjectCliniqueAddAfter(array $params): void
    {
        /** @var ClinicEmailRedirectionManager $redirectionManager */
        $redirectionManager = $this->getContainer()
            ->get(ClinicEmailRedirectionManager::class);

        if ($params['object']->email_original) {
            $redirectionManager->setRedirection($params['object']->code_privilege, $params['object']->email_original);
        }
    }

    /**
     * @param array{object: Clinique} $params
     */
    public function hookActionObjectCliniqueUpdateAfter(array $params): void
    {
        /** @var ClinicEmailRedirectionManager $redirectionManager */
        $redirectionManager = $this->getContainer()
            ->get(ClinicEmailRedirectionManager::class);

        if ($params['object']->email_original) {
            $redirectionManager->setRedirection($params['object']->code_privilege, $params['object']->email_original);
        }
    }

    /**
     * @param array{object: Customer} $params
     */
    public function hookActionObjectCustomerAddAfter(array $params): void
    {
        $this->syncCustomerWithPhpList($params['object']);
    }

    /**
     * @param array{object: Customer} $params
     */
    public function hookActionObjectCustomerUpdateAfter(array $params): void
    {
        $this->syncCustomerWithPhpList($params['object']);
    }

    /**
     * @param array{product: Product, quantity: int, id_product_attribute: int} $params
     */
    public function hookActionCartUpdateQuantityBefore(array $params): void
    {
        $context = \Context::getContext();
        \assert(null !== $context);

        $clinique = Clinique::getCliniqueByGroupId((int) $context->customer->id_default_group);

        // Pas de clinique trouvée ou clinique pas centravet ? Pas de filtre
        if (!$clinique || 'centravet' !== $clinique->centrale) {
            return;
        }

        $api = $this->getCentraVetStockClient();

        if (!$api) {
            return;
        }

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

        $db = Db::getInstance();
        $reference = $db->getValue(
            'SELECT `product_supplier_reference`'
            . ' FROM `' . _DB_PREFIX_ . 'product_supplier`'
            . ' WHERE id_product = ' . (int) $product->id
            . ' AND `id_product_attribute` = ' . (int) $params['id_product_attribute']
            . ' AND `id_supplier` = 1'
        );

        try {
            if (!$api->checkStock($clinique->code_client, (string) $reference, $quantity)) {
                // Empêche l'ajout au produit
                $product->available_for_order = false;

                // Pour les petites commandes, on passe le produit hors stock
                if ($quantity <= 2) {
                    $request = 'UPDATE `' . _DB_PREFIX_ . 'stock`'
                        . ' SET `physical_quantity` = 0, `usable_quantity` = 0'
                        . ' WHERE `id_warehouse` = ' . (int) $clinique->id_warehouse
                        . ' AND `id_product` = ' . (int) $product->id
                        . ' AND `id_product_attribute` = ' . (int) $params['id_product_attribute'];

                    $db->execute($request);
                    if (StockAvailable::dependsOnStock((int) $product->id)) {
                        // synchronizes
                        StockAvailable::synchronize((int) $product->id);
                    }
                }
            }
        } catch (\Exception $e) {
            Logger::addLog(
                $e->getMessage(),
                1,
                $e->getCode(),
                CentravetStockApi::class,
                null,
                true
            );
        }
    }

    /**
     * On ajoute le champ "Code privilège" dans le formulaire de création/modification de compte client.
     *
     * @param array{fields: array<string, FormField>} $parameters
     *
     * @return array<string, FormField>
     */
    public function hookAdditionalCustomerFormFields(array $parameters): array
    {
        $context = \Context::getContext();
        \assert(null !== $context);

        $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 (null !== $clinique && !$clinique->deleted) {
                $group = new Group($this->context->customer->id_default_group, $context->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(
                fn (FormField $field) => $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;
    }

    /**
     * @param array{fields: array<string, FormField>} $parameters
     *
     * @return array<string, FormField>
     */
    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(strval($code));

                    if (null === $clinique || $clinique->isCliniqueTest() || $clinique->deleted) {
                        $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 s'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{newCustomer: Customer} $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionCustomerAccountAdd(array $params): void
    {
        $customer = $params['newCustomer'];
        $codePrivilege = strval(Tools::getValue('code_privilege'));

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

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

            if ($group) {
                $groupDefaultId = (int) $group->id;
            } else {
                $groupDefaultId = 3;
            }

            // 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{customer: Customer} $parameters
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionCustomerAccountUpdate(array $parameters): void
    {
        $parameters['newCustomer'] = $parameters['customer'];

        $this->hookActionCustomerAccountAdd($parameters);
    }

    /**
     * @param array{newOrderStatus: OrderState, id_order: int} $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionOrderStatusUpdate(array $params): void
    {
        $context = \Context::getContext();
        \assert(null !== $context);
        $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 (Exception $exception) {
                        // Inhibiteur d'erreurfff
                        // 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);
        }

        // Envoit de la facture par email à la clinique
        $clinique = Clinique::getCliniqueByCarrierId((int) $order->id_carrier);

        if ($clinique && 4 == $newOrderStatus->id && $clinique->email_factures) {
            $customer = new Customer($order->id_customer);

            // Envoi de la facture par email à la clinique
            $data = [
                '{lastname}' => $customer->lastname,
                '{firstname}' => $customer->firstname,
                '{id_order}' => (int) $order->id,
                '{order_name}' => $order->getUniqReference(),
            ];

            $invoice = $order->getInvoicesCollection();
            $file_attachement = [];

            if ($order->invoice_number) {
                $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty);
                $file_attachement['invoice']['content'] = $pdf->render(false);
                $file_attachement['invoice']['name'] = Configuration::get(
                    'PS_INVOICE_PREFIX',
                    (int) $order->id_lang,
                    null, $order->id_shop
                )
                    . sprintf('%06d', $order->invoice_number) . '.pdf';
                $file_attachement['invoice']['mime'] = 'application/pdf';
            } else {
                $file_attachement = null;
            }

            Mail::Send(
                (int) $order->id_lang,
                'clinique_template_facture',
                'Facture commande ' . $order->id,
                $data,
                $clinique->code_privilege . '@myvetshop.fr',
                $clinique->name,
                null,
                null,
                $file_attachement,
                null,
                __DIR__ . '/mails/',
                false,
                (int) $order->id_shop
            );
        }
    }

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

    /**
     * @param array<mixed> $params
     */
    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{extra_template_vars?: array<string, mixed>} $params
     *
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionGetExtraMailTemplateVars(array $params): void
    {
        $context = \Context::getContext();
        \assert(null !== $context);

        // Uniquement pour les e-mails "shipped" (lors de l'envoi du colis)
        if (!isset($params['template'])
            || !isset($params['template_vars'])
            || !\is_array($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';

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

        // Chargement des informations
        $clinique = new Clinique($idClinique);
        $store = new Store($clinique->id_store, $context->language->id);

        // ///////////////////////////////////////
        // / Génération du texte l'e-mail
        $orderHtml = '';
        switch (Clinique::getCarrierType((int) $order->id_carrier)) {
            case Clinique::CARRIER_CLINIQUE:
                switch ($params['template']) {
                    case 'order_clinique':
                        $orderHtml = 'Votre clinique <strong>' . $store->name . '</strong> est ouverte aux'
                            . ' horaires suivants :';
                        break;

                    default:
                        $orderHtml = '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 :';
                }
                $orderHtml .= "<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";
                    }
                }

                $orderHtml .= $horaires_html;

                switch ($params['template']) {
                    case 'order_clinique':
                        $orderHtml .= '<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:
                $orderHtml = "Elle sera livrée directement à l'adresse de livraison que vous avez indiqué :<br/>\n";
                $addressDelivery = new Address($order->id_address_delivery);

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

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

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

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

        // Gestion automatique du mode "application mobile"
        if (\is_numeric($mobileAppFlag)) {
            if (1 === (int) $mobileAppFlag) {
                $this->context->cookie->mobile_app = 1;
            } else {
                unset($this->context->cookie->mobile_app);
            }
            $this->context->cookie->write();
        }

        if ($this->context->cookie->mobile_app) {
            if ($this->context->controller instanceof FrontController) {
                $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((int) $this->context->customer->id_default_group);

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

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

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

            // Récupération de la date de dernière commande
            $idLastOrder = Db::getInstance(false)
                ->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((int) $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{operator: string, cart: Cart, product: Product, quantity: int} $params
     */
    public function hookActionBeforeCartUpdateQty(array $params): void
    {
        if ('up' === $params['operator']) {
            if (
                !LimitedNumberOfProductByOrder::canBuyProduct(
                    $params['cart'],
                    $params['product'],
                    (int) $params['quantity']
                )
            ) {
                $params['product']->available_for_order = false;
            }
        }
    }

    public function hookDisplayAddRecoLink(): string
    {
        return $this->display(__FILE__, 'add_reco.tpl');
    }

    /**
     * @param array{object: MyvetshopTheme} $parameters
     */
    public function hookActionObjectMyvetshopThemeAddAfter(array $parameters): void
    {
        $this->hookActionObjectMyvetshopThemeUpdateAfter($parameters);
    }

    /**
     * @param array{object: MyvetshopTheme} $parameters
     */
    public function hookActionObjectMyvetshopThemeUpdateAfter(array $parameters): void
    {
        $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',
                    '$color_2',
                    '$color_3',
                    '$color_4',
                    '$color_5',
                ],
                [
                    $theme->color_1,
                    $theme->color_2,
                    $theme->color_3,
                    $theme->color_4,
                    $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 = \intval(\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 instanceof FrontController
            ) {
                $this->context->controller->registerStylesheet(
                    'myvetshop-theme-' . $theme->id,
                    $this->getPathUri() . '/css/theme/build/' . $theme->getFilename(),
                    ['priority' => 25]
                );
            }
        }
    }

    public function hookActionControllerInitAfter(): void
    {
        if (
            $this->context
            && $this->context->customer instanceof Customer
            && $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;
                    $theme = $clinique->hasTheme() ? $clinique->getTheme() : null;
                    $this->context->cookie->theme_privilege = $theme ? $theme->id : null;
                } else {
                    unset($this->context->cookie->theme_privilege);
                    unset($this->context->cookie->id_clinique);
                }
            }
        }
    }

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

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

    /**
     * @param array{carrier: array{id: int}} $parameters
     *
     * @return string
     */
    public function hookDisplayCarrierExtraContent(array $parameters): string
    {
        $carrierId = (int) $parameters['carrier']['id'];
        $carrier = new Carrier($carrierId);

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

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

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

        return '';
    }

    /**
     * @param array{
     *     search_query_builder: \Doctrine\DBAL\Query\QueryBuilder,
     *     count_query_builder: \Doctrine\DBAL\Query\QueryBuilder
     * } $parameters
     */
    public function hookActionAddressGridQueryBuilderModifier(array $parameters): void
    {
        $context = \Context::getContext();
        \assert(null !== $context);
        $cookieParameters = $context->cookie->getAll();

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

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

            $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
            );

            $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
            );
        }
    }

    /**
     * @param array{join: string} $parameters
     */
    public function hookActionAdminCartsListingFieldsModifier(array $parameters): void
    {
        $context = \Context::getContext();
        \assert(null !== $context);

        $cookieParameters = $context->cookie->getAll();

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

            $clinique = Clinique::getCliniqueByEmployeeId($employeeId);
            $groupId = 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;
        }
    }

    /**
     * @param array{
     *     search_query_builder: \Doctrine\DBAL\Query\QueryBuilder,
     *     count_query_builder: \Doctrine\DBAL\Query\QueryBuilder
     * } $parameters
     */
    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'
            );
    }

    /**
     * @param array{
     *     definition: \PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface
     * } $parameters
     */
    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(): void
    {
        if (
            $this->context->controller instanceof AdminDashboardController
            && $this->context->employee
            && 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 getCentraVetApiUrlDefaultValue(): string
    {
        return (string) \Configuration::get(
            self::CENTRAVET_API_URL,
            null,
            null,
            null,
            ''
        );
    }

    public function getCentraVetApiUserDefaultValue(): string
    {
        return (string) \Configuration::get(
            self::CENTRAVET_API_USER,
            null,
            null,
            null,
            ''
        );
    }

    public function getCentraVetApiPassDefaultValue(): string
    {
        return (string) \Configuration::get(
            self::CENTRAVET_API_PASS,
            null,
            null,
            null,
            ''
        );
    }

    public function install(): bool
    {
        $result = parent::install()
            && $this->installTables()
            && $this->registerHook('actionObjectCliniqueAddAfter')
            && $this->registerHook('actionObjectCliniqueUpdateAfter')
            && $this->registerHook('actionObjectCustomerAddAfter')
            && $this->registerHook('actionObjectCustomerUpdateAfter')
            && $this->registerHook('actionCartUpdateQuantityBefore')
            && $this->registerHook('actionCustomerUpdate')
            && $this->registerHook('actionCustomerAccountAdd')
            && $this->registerHook('actionCustomerAccountUpdate')
            && $this->registerHook('actionOrderStatusUpdate')
            && $this->registerHook('customerAccount')
            && $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');

        // URL personnalisée
        $metaRaw = Meta::getMetaByPage('module-myvetshopclinique-myreco', 1);
        if (!\is_array($metaRaw) || !isset($metaRaw['id_meta'])) {
            $meta = new Meta();
            $meta->page = 'module-myvetshopclinique-myreco';
            $meta->configurable = 1;
            $meta->save();
        } else {
            $meta = new Meta((int) $metaRaw['id_meta']);
        }
        Db::getInstance()
            ->execute('INSERT INTO `' . _DB_PREFIX_ . 'meta_lang`'
                . ' (`id_meta`, `id_shop`, `id_lang`, `title`, `description`, `url_rewrite`)'
                . ' VALUES (' . (int) $meta->id . ', 1, 1, "Mes recommandations", "Mes recommandations", "reco")'
                . ' ON DUPLICATE KEY UPDATE `url_rewrite` = "reco"');

        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)
            );
            \Configuration::updateValue(
                static::CENTRAVET_API_URL,
                \Tools::getValue(self::CENTRAVET_API_URL)
            );
            \Configuration::updateValue(
                static::CENTRAVET_API_USER,
                \Tools::getValue(self::CENTRAVET_API_USER)
            );
            if (\Tools::getValue(self::CENTRAVET_API_PASS)) {
                \Configuration::updateValue(
                    static::CENTRAVET_API_PASS,
                    \Tools::getValue(self::CENTRAVET_API_PASS)
                );
            }
        }
    }

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

        $fieldsForm = [
            '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)',
                    ],
                    [
                        'name' => self::CENTRAVET_API_URL,
                        'label' => $this->l('URL API Stock CentraVet'),
                        'type' => 'text',
                        'placeholder' => 'http://transnet.centravet.net (laisser blanc pour désactiver)',
                    ],
                    [
                        'name' => self::CENTRAVET_API_USER,
                        'label' => $this->l('Utilisateur API Stock CentraVet'),
                        'type' => 'text',
                    ],
                    [
                        'name' => self::CENTRAVET_API_PASS,
                        'label' => $this->l('Mot de passe API Stock CentraVet'),
                        'type' => 'password',
                    ],
                ],
                'submit' => [
                    'title' => $this->l('Save'),
                ],
            ],
        ];

        \assert($this->context->controller instanceof AdminController);

        $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') ?: 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([$fieldsForm]);
    }

    /**
     * @return array<mixed>
     */
    protected function getFieldsValues(): array
    {
        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()),
            static::CENTRAVET_API_URL => \Tools::getValue(
                static::CENTRAVET_API_URL,
                $this->getCentraVetApiUrlDefaultValue()
            ),
            static::CENTRAVET_API_USER => \Tools::getValue(
                static::CENTRAVET_API_USER,
                $this->getCentraVetApiUserDefaultValue()
            ),
            static::CENTRAVET_API_PASS => \Tools::getValue(static::CENTRAVET_API_PASS),
        ];
    }

    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
        );

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

        $allValues = \Tools::getAllValues();
        \assert(is_array($allValues));
        $addressForm->fillWith($allValues);

        return $addressForm;
    }

    protected function installTables(): bool
    {
        $queryCarrier = 'ALTER TABLE `' . _DB_PREFIX_ . 'carrier`
            ADD COLUMN IF NOT EXISTS `domicile` INT(1) NOT NULL DEFAULT 0';
        $queryStore = 'ALTER TABLE `' . _DB_PREFIX_ . 'store`
            ADD COLUMN IF NOT EXISTS `website` VARCHAR(100) DEFAULT NULL';

        return \Db::getInstance()->execute($queryCarrier)
            && \Db::getInstance()->execute($queryStore)
            && Clinique::install()
            && MyvetshopCliniqueShipping::install()
            && CliniqueHolidays::install()
            && CliniquePush::install()
            && OAuthClient::install()
            && OAuthAuthCode::install()
            && OAuthAccessToken::install()
            && EstablishmentEvent::install()
            && ExportProduct::install()
            && Recommandation::install()
            && BuyLimitedNumberOfProducts::install()
            && MyvetshopVeterinaire::install()
            && MyvetshopTheme::install()
            && MyvetshopRecommandationProduct::install();
    }

    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);
    }

    public function getCentraVetStockClient(): ?CentravetStockApi
    {
        $centravetApiUrl = \Configuration::get(self::CENTRAVET_API_URL);
        $centravetApiUser = \Configuration::get(self::CENTRAVET_API_USER);
        $centravetApiPass = \Configuration::get(self::CENTRAVET_API_PASS);

        // Api non configuré ? On arrête là
        if (!$centravetApiUrl || !$centravetApiUser || !$centravetApiPass) {
            return null;
        }

        return new CentravetStockApi(
            \Cache::getInstance(),
            new \GuzzleHttp\Client(),
            $centravetApiUrl,
            $centravetApiUser,
            $centravetApiPass,
        );
    }
}
