<?php

namespace PrestaShop\Module\LCVPrestaConnector\Controller;

use PrestaShop\Module\LCVPrestaConnector\SyncConfiguration;
use Symfony\Component\HttpFoundation\Request;

/**
 * Gestion des méta-catégories.
 *
 * Une méta-catégorie est une catégorie virtuelle côté backoffice, construite
 * par le module comme la combinaison logique de plusieurs catégories dynamiques
 * existantes. Une fois créée, elle se comporte comme une catégorie ordinaire
 * dans la grille de mappage.
 *
 * Stockage : SyncConfiguration::CFG_META_CATEGORIES
 *   { guid => [nom, code_cat_1, code_cat_2, ...] }
 *
 *   - le GUID est préfixé par "metacat_" pour être reconnaissable côté moteur
 *     (cf. MappageAdminController::mappingCategoryAction et
 *     BridgeAdapter::pullProducts) ;
 *   - le premier élément du tableau est toujours le nom ;
 *   - les éléments suivants sont les codes des catégories dynamiques composantes,
 *     triés en ordre croissant.
 *
 * La méta-catégorie n'est pas modifiable après création (cela invaliderait
 * tous les mappages déjà positionnés). Pour la modifier : la supprimer puis
 * la recréer.
 */
class MetaCategoriesAdminController extends AdminController
{
    /**
     * On enrechit la configuration de la barre d'outils
     * 
     * @return array
     */
    protected function getAdminLayoutToolBar() : array 
    {
        $toolbar = parent::getAdminLayoutToolBar();

        $mustLogin = $this->checkLogin();

        if ($mustLogin)
            $toolbar = [];

        $toolbar['mapping'] = [
                    'href' => $this->generateUrl($this->module->name . '_map_category'),
                    'class' => 'btn-outline-secondary pc-toolbar-button',
                    'desc' => 'Mappings',
                    'help' => 'Configurer les mappings',
                    'icon' => 'map',                    
                ];

        if (!$mustLogin)
            $toolbar['bind'] = [
                        'href' => $this->generateUrl($this->module->name . '_configuration') . '&reset-binding=1',
                        'class' => 'btn-outline-secondary pc-toolbar-button',
                        'desc' => 'Déconnecter',
                        'help' => '⚠⚠⚠ Déconnecte le module de votre backoffice. Vous devrez vous reconnecter pour continuer à utiliser le module.',
                        'icon' => 'cancel',                    
                    ];
        else
            $toolbar['bind'] = [
                'href' => $this->generateUrl($this->module->name . '_configuration') . '',
                'class' => 'btn-outline-secondary pc-toolbar-button',
                'desc' => 'Associer',
                'help' => 'Associe le module à votre backoffice '.$this->module->getBridge()->getId().'.',
                'icon' => 'login',
            ];

        return $toolbar;
    }
    
    /**
     * Page principale : liste + formulaire de création + suppression.
     *
     * Actions supportées en POST (champ caché 'action') :
     *   - "create" : crée une nouvelle méta-catégorie ;
     *   - "delete" : supprime une méta-catégorie et ses mappings associés.
     */
    public function indexAction(Request $request)
    {
        $cfg = $this->module->getCfg();

        // Catégories dynamiques NON virtuelles (uniquement celles du backoffice).

        // On insère des catégories dynamiques spéciales pour les champs "marque"
        $dynCats['__manufacturer'] = 'Marque';
        
        // puis on lit directement CFG_DYN_CAT (et non CategoriesManager::getDynCatsTypes()
        // qui injecte déjà les méta-catégories) pour empêcher qu'une méta-catégorie
        // soit composante d'une autre méta-catégorie.
        foreach ($cfg->get(SyncConfiguration::CFG_DYN_CAT) ?? [] as $code => $label)
            $dynCats[$code] = $label;

        // Traitement des actions POST
        if ($request->isMethod('POST'))
        {
            $action = $request->request->get('action');

            try
            {
                if ($action === 'create')
                {
                    $this->createMetaCategory($request, $dynCats);
                }
                else if ($action === 'delete')
                {
                    $this->deleteMetaCategory($request);
                }
            }
            catch (\Exception $e)
            {
                $this->addFlash('error', $e->getMessage());
            }

            // Redirection POST/GET pour éviter le repost au reload
            return $this->redirectToRoute($request->attributes->get('_route'));
        }

        // ── Affichage ────────────────────────────────────────────────────────
        $metaCats = $cfg->get(SyncConfiguration::CFG_META_CATEGORIES) ?? [];

        // Construction des lignes pour l'affichage
        $rows = [];
        foreach ($metaCats as $guid => $definition)
        {
            $name       = $definition[0] ?? '';
            $components = array_slice($definition, 1);

            $componentLabels = [];
            foreach ($components as $code)
                $componentLabels[] = $dynCats[$code] ?? ('?? '.$code);

            $rows[] = [
                'guid'            => $guid,
                'name'            => $name,
                'componentLabels' => $componentLabels,
            ];
        }

        return $this->render(
            '@Modules/' . $this->module->name . '/views/templates/admin/meta_categories.html.twig',
            $this->addDefaultVars([
                'dynCats'  => $dynCats,
                'metaRows' => $rows,
            ])
        );
    }

    /**
     * Création d'une méta-catégorie.
     *
     * @throws \Exception en cas de validation invalide
     */
    private function createMetaCategory(Request $request, array $dynCats) : void
    {
        $name = trim((string) $request->request->get('name', ''));
        if ($name === '')
            throw new \Exception('Le nom de la méta-catégorie est obligatoire.');

        $components = $request->request->all('components');        
        if (!is_array($components) || count($components) < 2)
            throw new \Exception('Une méta-catégorie doit comporter au moins deux catégories composantes.');

        // Validation : toutes les composantes doivent être des catégories dynamiques non virtuelles
        foreach ($components as $code)
        {
            if (!array_key_exists($code, $dynCats))
                throw new \Exception('Catégorie composante inconnue : ' . $code);
        }

        // Tri croissant sur le code interne
        sort($components);

        // Le guid de la catégorie méta n'est pas un vrai guid, mais un identifiant unique : metacat_1, metacat_2, etc.
        // on localise le dernier metacat_X où X est un entier (sinon, si ce n'est pas un entier, on considère que c'est à 0)
        // et on incrémente X de 1 pour générer le guid de la nouvelle méta-catégorie.
        $maxMetacatId = 0;
        $cfg = $this->module->getCfg();
        $metaCats = $cfg->get(SyncConfiguration::CFG_META_CATEGORIES) ?? [];
        foreach ($metaCats as $existingGuid => $definition)
        {
            if (strpos($existingGuid, 'metacat_') === 0)
            {
                $num = intval(substr($existingGuid, strlen('metacat_')));
                if ($num > $maxMetacatId)
                    $maxMetacatId = $num;
            }
        }

        // Génération du GUID préfixé "metacat_" (pattern reconnu par MappageAdminController)
        $guid = 'metacat_' . ($maxMetacatId + 1);        

        // Stockage : [nom, code_cat_1, code_cat_2, ...]
        $metaCats[$guid] = array_merge([$name], $components);
        $cfg->set(SyncConfiguration::CFG_META_CATEGORIES, $metaCats);

        $this->addFlash('success', 'Méta-catégorie « ' . $name . ' » créée. Elle apparaîtra dans le mapping des catégories au fur et à mesure que la synchronisation rencontrera ses combinaisons de valeurs.');
    }

    /**
     * Suppression définitive d'une méta-catégorie et de tous ses mappings associés.
     *
     * @throws \Exception en cas de GUID invalide
     */
    private function deleteMetaCategory(Request $request) : void
    {
        $guid = trim((string) $request->request->get('guid', ''));
        if ($guid === '')
            throw new \Exception('GUID manquant.');

        $cfg      = $this->module->getCfg();
        $metaCats = $cfg->get(SyncConfiguration::CFG_META_CATEGORIES) ?? [];

        if (!array_key_exists($guid, $metaCats))
            throw new \Exception('Méta-catégorie introuvable.');

        $name = $metaCats[$guid][0] ?? $guid;

        // Suppression de la définition
        unset($metaCats[$guid]);
        $cfg->set(SyncConfiguration::CFG_META_CATEGORIES, $metaCats);

        // Suppression du mappage et des éventuelles données annexes (labels, exdata)
        // associées à cette méta-catégorie.
        $db  = \Db::getInstance();
        $pfx = $this->module->TblPrefix;

        foreach ([
            SyncConfiguration::CFG_MAP_DYN_CAT . $guid,
            SyncConfiguration::CFG_MAP_DYN_CAT . $guid . '_name',
            SyncConfiguration::CFG_MAP_DYN_CAT . $guid . '_exdata',
        ] as $cfgKey)
        {
            $db->execute(
                'DELETE FROM `' . $pfx . 'configuration` WHERE `key` = \'' . pSQL($cfgKey) . '\''
            );
        }

        $this->addFlash('success', 'Méta-catégorie « ' . $name . ' » supprimée ainsi que tous ses mappages associés.');
    }
}