<?php

namespace PrestaShop\Module\LCVPrestaTheme\Installer;

use Context;
use Db;
use Language;
use Module;
use Profile;
use Tab;
use Hook;
use PrestaShopLogger;
use PrestaShop\Module\LCVPrestaTheme\Classes\ThemeTools;
use LCVPrestaTheme;

class Install
{
    /*
     * Fonction de test pour vérifier si le module est prêt.
     */
    public static function tests() : bool
    {
        return true;
    }

    /**
     * Active par défaut les optimisations de performance PrestaShop (CCC) :
     * combinaison + minification du CSS/JS, defer du JS et minification du HTML.
     * Le thème est maîtrisé (assets valides) → ces réglages sont sûrs et divisent
     * fortement le nombre de requêtes et le render-blocking.
     */
    public static function setPerformanceDefaults(): bool
    {
        \Configuration::updateValue('PS_CSS_THEME_CACHE', 1);        // combine + minifie le CSS
        \Configuration::updateValue('PS_JS_THEME_CACHE', 1);         // combine + minifie le JS
        \Configuration::updateValue('PS_JS_DEFER', 1);               // <script defer>
        \Configuration::updateValue('PS_HTML_THEME_COMPRESSION', 1); // minifie le HTML rendu

        return true;
    }

    public static function installTheme(Module $module): bool
    {
        $source = _PS_MODULE_DIR_ . $module->name . '/assets/presta_theme';
        $destination = _PS_ALL_THEMES_DIR_ . 'presta_theme';        

        if (!ThemeTools::copyTheme($source, $destination)) {
            PrestaShopLogger::addLog("❌ Échec de la copie du thème depuis $source vers $destination", 3);
            return false;
        }

        PrestaShopLogger::addLog("✅ Thème 'presta_theme' copié avec succès.", 1);

        // Nouveau thème MÉRIDIAN : déployé et rendu disponible (non activé automatiquement).
        $meridianSrc = _PS_MODULE_DIR_ . $module->name . '/assets/meridian';
        $meridianDst = _PS_ALL_THEMES_DIR_ . 'meridian';
        if (is_dir($meridianSrc)) {
            if (ThemeTools::copyTheme($meridianSrc, $meridianDst)) {
                PrestaShopLogger::addLog("✅ Thème 'meridian' copié avec succès.", 1);
            } else {
                PrestaShopLogger::addLog("⚠️ Échec de la copie du thème 'meridian' depuis $meridianSrc vers $meridianDst", 2);
            }
        }

        self::installMailTheme($module);

        return true;
    }

    /**
     * Thème d'email MÉRIDIAN.
     *
     * Les .html/.txt déjà générés voyagent avec assets/meridian/mails (copié par
     * installTheme) et sont servis directement par Mail::send depuis
     * themes/meridian/mails. Ici on déploie en plus les sources Twig dans
     * mails/themes/meridian (pour permettre la régénération/sélection depuis le
     * back-office « Design > E-mail ») et on active le thème.
     */
    public static function installMailTheme(Module $module): bool
    {
        $src = _PS_MODULE_DIR_ . $module->name . '/mails/themes/meridian';
        $dst = _PS_ROOT_DIR_ . '/mails/themes/meridian';

        if (!is_dir($src)) {
            return false;
        }

        if (ThemeTools::copyTheme($src, $dst)) {
            \Configuration::updateValue('PS_MAIL_THEME', 'meridian');
            PrestaShopLogger::addLog("✅ Thème d'email 'meridian' déployé et activé.", 1);

            return true;
        }

        PrestaShopLogger::addLog("⚠️ Échec du déploiement du thème d'email 'meridian' depuis $src vers $dst", 2);

        return false;
    }

    /**
     * Statut de commande « Click & Collect ».
     *
     * Crée un état de commande « Prêt pour retrait en boutique » qui, une fois
     * appliqué à une commande depuis le back-office, envoie automatiquement
     * l'email `click_collect` au client (template du thème email meridian).
     *
     * Idempotent : l'id de l'état est mémorisé dans la config (pt_OS_CLICK_COLLECT)
     * pour ne pas recréer de doublon à chaque install/update.
     */
    public static function installClickCollectOrderState(Module $module): bool
    {
        $configKey = \LCVPrestaTheme::MODULE_PREFIX . 'OS_CLICK_COLLECT';

        $existingId = (int) \Configuration::get($configKey);
        if ($existingId) {
            $existing = new \OrderState($existingId);
            if (\Validate::isLoadedObject($existing)) {
                return true;
            }
        }

        $orderState = new \OrderState();
        $orderState->send_email = true;
        $orderState->module_name = $module->name;
        $orderState->color = '#f2ca02';
        $orderState->logable = true;
        $orderState->invoice = false;
        $orderState->shipped = false;
        $orderState->paid = false;
        $orderState->delivery = false;
        $orderState->hidden = false;
        $orderState->unremovable = false;
        $orderState->pdf_invoice = false;
        $orderState->pdf_delivery = false;

        $names = [];
        $templates = [];
        foreach (Language::getLanguages(false) as $lang) {
            $names[(int) $lang['id_lang']] = 'Prêt pour retrait en boutique';
            $templates[(int) $lang['id_lang']] = 'click_collect';
        }
        $orderState->name = $names;
        $orderState->template = $templates;

        if ($orderState->add()) {
            \Configuration::updateValue($configKey, (int) $orderState->id);
            PrestaShopLogger::addLog("✅ Statut de commande 'Click & Collect' créé (id " . (int) $orderState->id . ").", 1);

            return true;
        }

        PrestaShopLogger::addLog("⚠️ Échec de création du statut de commande 'Click & Collect'.", 2);

        return false;
    }

    public static function uninstallTheme(): bool
    {
        $themeDir = _PS_ALL_THEMES_DIR_ . 'presta_theme';

        try {
            ThemeTools::removeDirectory($themeDir);
            ThemeTools::removeDirectory(_PS_ALL_THEMES_DIR_ . 'meridian');
            // Thème d'email : retire les sources Twig et repasse sur 'modern'.
            ThemeTools::removeDirectory(_PS_ROOT_DIR_ . '/mails/themes/meridian');
            \Configuration::updateValue('PS_MAIL_THEME', 'modern');
            PrestaShopLogger::addLog("🗑️ Thèmes supprimés : presta_theme, meridian (+ thème email)", 1);
        } catch (\Exception $e) {
            PrestaShopLogger::addLog("❌ Erreur lors de la suppression du thème : " . $e->getMessage(), 3);
            return false;
        }

        $idShop = (int) Context::getContext()->shop->id;
        $sql = 'UPDATE `' . _DB_PREFIX_ . 'shop` SET `theme_name` = "classic" WHERE `id_shop` = ' . $idShop;

        if (Db::getInstance()->execute($sql)) {
            PrestaShopLogger::addLog("✅ Thème 'classic' réactivé pour la boutique ID $idShop", 1);
            return true;
        } else {
            PrestaShopLogger::addLog("❌ Échec de la réactivation du thème 'classic' pour la boutique ID $idShop", 3);
            return false;
        }
    }

    public static function installEmployeeProfile(): bool
    {
        $langId = Context::getContext()->language->id;
        $profileName = 'Gérant';

        $profiles = Profile::getProfiles($langId);
        foreach ($profiles as $profile) {
            if ($profile['name'] === $profileName) {
                PrestaShopLogger::addLog("ℹ️ Profil '$profileName' déjà existant (ID {$profile['id_profile']}). Permissions mises à jour.", 1);
                return self::setProfilePermissions((int)$profile['id_profile']);
            }
        }

        $profile = new Profile();
        foreach (Language::getLanguages() as $lang) {
            $profile->name[$lang['id_lang']] = $profileName;
        }

        if (!$profile->add()) {
            PrestaShopLogger::addLog("❌ Échec de la création du profil '$profileName'.", 3);
            return false;
        }

        PrestaShopLogger::addLog("✅ Profil '$profileName' créé avec succès (ID {$profile->id}).", 1);
        return self::setProfilePermissions((int)$profile->id);
    }

    private static function setProfilePermissions(int $profileId): bool
    {
        $authorizedRoles = [5, 6, 7, 8, 21, 22, 23, 24, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
            46, 47, 48, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 93,
            94, 95, 96, 125, 126, 127, 128, 149, 150, 151, 152, 177, 178, 179, 180, 185,
            186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 205,
            206, 207, 208, 213, 214, 215, 216, 225, 226, 227, 228, 245, 246, 247, 248, 281,
            282, 283, 284, 305, 306, 307, 308, 317, 318, 319, 320, 341, 342, 343, 344, 345,
            346, 347, 348, 421, 422, 423, 424, 425, 426, 427, 428, 873, 874, 875, 876];

        $success = true;
        foreach ($authorizedRoles as $idRole) {
            $exists = (bool)Db::getInstance()->getValue(
                'SELECT 1 FROM ' . _DB_PREFIX_ . 'access WHERE id_profile = ' . (int)$profileId . ' AND id_authorization_role = ' . (int)$idRole
            );

            if (!$exists) {
                $result = Db::getInstance()->insert('access', [
                    'id_profile' => $profileId,
                    'id_authorization_role' => $idRole,
                ]);

                if (!$result) {
                    PrestaShopLogger::addLog("❌ Échec de l’insertion de la permission $idRole pour le profil ID $profileId.", 3);
                    $success = false;
                }
            }
        }

        return $success;
    }

    public static function hidePrestaShopBackOfficeIdentity(Module $module): bool
    {
        $filesToReplace = [            
            // Fichier de layout de login
            'login-layout' => [
                'source' => _PS_MODULE_DIR_ . $module->name . '/views/prestashop/login_layout.html.twig',
                'target' => _PS_ROOT_DIR_ . '/src/PrestaShopBundle/Resources/views/Admin/Layout/login_layout.html.twig',
            ],
        ];

        // On ajoute les fichiers CSS des thèmes de l'administration
        // Pour ça, on va trouver tous les répertoires admin* et dans chacun d'eux, on cherche un fichier theme.css
        // si on le trouve, on le remplace par l'équivalent dans le module
        $adminDirs = glob(_PS_ROOT_DIR_ . '/admin*/themes/*', GLOB_ONLYDIR);
        foreach ($adminDirs as $dir) {
            $themeCss = $dir . '/public/theme.css';
            if (file_exists($themeCss)) {
                $filesToReplace['theme-' . basename($dir)] = [
                    'source' => _PS_MODULE_DIR_ . $module->name . '/views/prestashop/' . basename($dir) . '/theme.css',
                    'target' => $themeCss,
                ];
            }
        }

        $success = true;

        foreach ($filesToReplace as $key => $paths) {
            if (!file_exists($paths['source'])) {
                PrestaShopLogger::addLog("❌ Fichier source manquant pour : $key", 3);
                $success = false;
                continue;
            }

            $backupPath = $paths['target'] . '.backup';
            if (file_exists($paths['target']) && !file_exists($backupPath)) {
                copy($paths['target'], $backupPath);
            }

            if (!copy($paths['source'], $paths['target'])) {
                PrestaShopLogger::addLog("❌ Échec de copie vers : " . $paths['target'], 3);
                $success = false;
            }
        }

        $faviconTarget = _PS_ROOT_DIR_ . '/img/favicon.ico';
        $faviconSource = _PS_MODULE_DIR_ . $module->name . '/views/PrestaShop/favicon.ico';
        $faviconBackup = $faviconTarget . '.backup';

        if (file_exists($faviconSource)) {
            if (file_exists($faviconTarget) && !file_exists($faviconBackup)) {
                copy($faviconTarget, $faviconBackup);
            }

            if (!copy($faviconSource, $faviconTarget)) {
                PrestaShopLogger::addLog("❌ Échec de la copie du favicon.", 3);
                $success = false;
            }
        }

        return $success;
    }

    public static function restorePrestaShopBackOfficeIdentity(): bool
    {
        $paths = [
            _PS_ROOT_DIR_ . '/admin-dev/themes/default/public/theme.css',
            _PS_ROOT_DIR_ . '/admin-dev/themes/new-theme/public/theme.css',
            _PS_ROOT_DIR_ . '/img/favicon.ico',
            _PS_ROOT_DIR_ . '/src/PrestaShopBundle/Resources/views/Admin/Layout/login_layout.html.twig',
        ];

        $success = true;

        foreach ($paths as $path) {
            $backup = $path . '.backup';

            // Si un fichier .backup existe
            if (file_exists($backup)) {
                // Supprimer le fichier actuel s'il existe
                if (file_exists($path)) {
                    if (!unlink($path)) {
                        $success = false;
                        continue;
                    }
                }

                // Restaurer le .backup => fichier original
                if (!copy($backup, $path)) {
                    $success = false;
                    continue;
                }

                // Supprimer le fichier .backup après restauration
                if (!unlink($backup)) {
                    $success = false;
                }
            }
        }

        return $success;
    }

    public static function installTab(LCVPrestaTheme $module): bool
    {
        $className = 'AdminLCVPrestaThemeController';
        $routeName = 'admin_presta_general';

        $tabId = (int) Tab::getIdFromClassName($className);
        $tab = new Tab($tabId ?: null);
        $tab->active = 1;
        $tab->class_name = $className;
        $tab->route_name = $routeName;

        foreach (Language::getLanguages() as $lang) {
            $tab->name[$lang['id_lang']] = 'Presta theme';
        }

        $tab->id_parent = (int) Tab::getIdFromClassName('AdminParentThemes');
        $tab->module = $module->name;

        return $tab->save();
    }

    public static function uninstallTab(): bool
    {
        $tabId = (int) Tab::getIdFromClassName('AdminLCVPrestaThemeController');
        if ($tabId) {
            $tab = new Tab($tabId);
            return $tab->delete();
        }
        return true;
    }

    public static function registerHooks(Module $module): bool
    {
        $hooks = [
            'actionDispatcher',
            'actionFrontControllerSetMedia',
            'actionObjectProductUpdateAfter',
            'actionObjectStockAvailableUpdateAfter',
            'actionFacetedSearchFilters',
            'displayBeforeBodyClosingTag',
            'displayHome', 'displayTop', 'displayBackOfficeHeader', 'displayHomeSliderFullWidth',
            'displayFooterBefore', 'displayDeliveryEstimation', 'displayFreeDelivery',
            'displaySociaux', 'displayFilter', 'displayHeader', 'displayBandeau', 'displayCookie', 'displayPopup', 'displayMagasin','displayPopupStore','displayNav2','displayWishlistButton', 'displayCustomerAccount','displayNav2','displayShippingEstimatorCheckout',
        ];

        $success = true;
        foreach ($hooks as $hook) {
            $hookId = Hook::getIdByName($hook);
            if (!$hookId) {
                $newHook = new Hook();
                $newHook->name = $hook;
                $newHook->title = ucfirst(str_replace('_', ' ', $hook));
                $newHook->description = "Hook LCVPrestaTheme pour '$hook'";
                $newHook->add();
            }
            if (!$module->registerHook($hook)) {
                $success = false;
            }
        }
        return $success;
    }

    public static function deleteModule(): bool
    {
        $modulesToDelete = [
        'ps_customtext', 'ps_featuredproducts', 'ps_imageslider', 'ps_mainmenu', 'ps_banner',
        'ps_categorytree', 'ps_socialfollow', 'productcomments', 'ps_googleanalytics', 'statscarrier',
        'statscatalog', 'statscheckup', 'statsdata', 'statsforecast', 'statsnewsletter',
        'statsproduct', 'statsregistrations', 'statssales', 'statssearch', 'statsstock',
        'statsbestvouchers', 'statsbestsuppliers', 'statsbestproducts', 'statsbestmanufacturers', 'statsbestcustomers',
        'statsbestcategories', 'psassistant', 'ps_sharebuttons', 'ps_categoryproducts', 'ps_cashondelivery',
        'ps_bestsellers', 'ps_brandlist', 'gridhtml', 'gamification', 'dashproducts',
        'dashgoals', 'ps_crossselling', 'ps_distributionapiclient', 'ps_eventbus', 'ps_mbo',
        'ps_themecusto', 'psshipping','ps_supplierlist','ps_specials','ps_newproducts','ps_apiresources','dashtrends','statspersonalinfos','blockreassurance','blockwishlist'
        ];


        $success = true;

        foreach ($modulesToDelete as $moduleName) {
            $moduleInstance = Module::getInstanceByName($moduleName);
            if (\Validate::isLoadedObject($moduleInstance)) {
                if (!$moduleInstance->uninstall()) {
                    PrestaShopLogger::addLog("❌ Échec de désinstallation : $moduleName", 3);
                    $success = false;
                    continue;
                }
                PrestaShopLogger::addLog("✅ Module désinstallé : $moduleName");
            }

            $modulePath = _PS_MODULE_DIR_ . $moduleName;
            if (is_dir($modulePath)) {
                try {
                    ThemeTools::removeDirectory($modulePath);
                    PrestaShopLogger::addLog("🗑️ Dossier supprimé : $moduleName");
                } catch (\Exception $e) {
                    PrestaShopLogger::addLog("❌ Erreur suppression dossier $moduleName : " . $e->getMessage(), 3);
                    $success = false;
                }
            }
        }

        return $success;
    }

    public static function wishlistDb()
    {
        // Création de la table wishlist
            $sql = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'wishlist` (
                `id_wishlist` INT(11) NOT NULL AUTO_INCREMENT,
                `id_customer` INT(11) NOT NULL,
                `id_product` INT(11) NOT NULL,
                `date_add` DATETIME NOT NULL,
                PRIMARY KEY (`id_wishlist`),
                UNIQUE KEY `wishlist_unique` (`id_customer`, `id_product`)
            ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';

            if (!Db::getInstance()->execute($sql)) {
                return false;
            }

            return true;
    }
}
