<?php

namespace PrestaShop\Module\LCVPrestaTheme\Controllers\Admin;

use phpDocumentor\Reflection\Types\Null_;
use PrestaShopBundle\Controller\Admin\PrestaShopAdminController;
use Symfony\Component\HttpFoundation\Request;
use PrestaShop\Module\LCVPrestaTheme\Classes\ThemeTools;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use PrestaShop\Module\LCVPrestaTheme\Config\ConfigTheme;
use PrestaShop\Module\LCVPrestaTheme\Forms\{MenuParentType, MenuChildType, GeneralType, MenuMediaType, StoreInfoType, StoreType};
use Symfony\Component\HttpFoundation\JsonResponse;
use PrestaShop\Module\LCVPrestaTheme\Classes\AbstractGroup;

/**
 * AdminFormController
 *
 * Contrôleur pour la gestion des formulaires du module LCVPrestaTheme
 */
class AdminFormController extends PrestaShopAdminController
{
    public function CreateConfigurationForm(
        Request $request,
        string $formType,
        string $className,
        int $id,
        ?string $action = null,
        string $objet,
        ?string $redirectRoute = null,
        ?bool $upload = null,
        string $title,
        ?int $parent_id = null,
        ?int $group_id = null,
    ) {
        $config = ConfigTheme::load();

        $menuColumn = false;
       

        if($action == null){
            if (!isset($config->$objet[0])) {
                $config->$objet[0] = new $className();
            }

            $configObject = $config->$objet[0];
            $id = 0;
            $action = 'edit';

        }else{
            /*
            |--------------------------------------------------------------------------
            | ADD
            |--------------------------------------------------------------------------
            */
            if ($action === 'add') {
                $configObject = new $className();
                $config->$objet[] = $configObject;
                if (property_exists($configObject, 'id')) {
                    $maxId = 0;
                    foreach ($config->$objet as $obj) {
                        if (isset($obj->id) && $obj->id > $maxId) {
                            $maxId = $obj->id;
                        }
                    }
                    $configObject->id = $maxId + 1;
                }

                if(method_exists($configObject, 'injectInto')){
                        $menuColumn = true;
                }


            }
            /*
            |--------------------------------------------------------------------------
            |  EDIT
            |--------------------------------------------------------------------------
            */
            elseif ($action === 'edit') {

                // si les objets utilisent un ID 
                if (property_exists(new $className(), 'id')) {

                    $configObject = null;

                    foreach ($config->$objet as $obj) {
                        if ((int)$obj->id === (int)$id) {
                            $configObject = $obj;
                            break;
                        }
                    }

                    if (!$configObject) {
                        throw new \Exception('Élément introuvable');
                    }

                } 
                // sinon on utilise l'index classique
                else {

                    if (!isset($config->$objet[$id])) {
                        throw new \Exception('Élément introuvable');
                    }

                    $configObject = $config->$objet[$id];
                    if(method_exists($configObject, 'injectInto')){
                        $menuColumn = true;
                    }

                }
            }
            /*
            |--------------------------------------------------------------------------
            | DELETE
            |--------------------------------------------------------------------------
            */
            elseif ($action === 'delete') {
                

                if (property_exists(new $className(), 'id')) {

                    $configObject = null;

                    foreach ($config->$objet as $index => $obj) {

                        if ((int)$obj->id === (int)$id) {

                            $configObject = $obj;

                            unset($config->$objet[$index]);

                            break;
                        }
                    }

                    if (!$configObject) {
                        throw new \Exception('Élément introuvable');
                    }

                    // réindexer
                    $config->$objet = array_values($config->$objet);

                    // suppression items dans group
                    if (method_exists($configObject, 'injectIntoGroup')) {
                        $configObject->injectIntoGroup($config, $action, $id, $group_id);
                        $params['group_id'] = $group_id;
                    }

                } 
                else {

                    $configObject = $config->$objet[$id];
                     if(method_exists($configObject, 'injectInto')){
                        $menuColumn = true;
                    }
                    unset($config->$objet[$id]);

                    $config->$objet = array_values($config->$objet);

                    // suppression colonne menu
                    if ($menuColumn) {
                        $configObject->injectInto(
                            $config->configMenuParent,
                            isset($_GET['column']) ? $_GET['column'] : $id,
                            $action
                        );

                        $params = $parent_id !== null ? ['parent_id' => $parent_id] : [];
                    }

                }

                $config->save();

                return $this->redirectToRoute($redirectRoute, $params ?? []);
            }

        }

        

     
        // Création du formulaire
        $form = $this->createForm($formType, null, $menuColumn ? ['parent_id' => $parent_id] : []);
        $form->handleRequest($request);
   

        if(method_exists($formType, 'getIntro')){
            $intro= $formType::getIntro();
        }

        // Initialise un tableau pour sauvegarder les images existantes avant la soumission du formulaire
        $existingImages = [];
        // Vérifie si le formulaire en cours est de type MenuMediaType ET qu'il existe au moins un média dans l'objet de config
        if ($formType === MenuMediaType::class && !empty($configObject->medias)) {
            // Parcourt chaque entrée dans la collection de médias existante
            foreach ($configObject->medias as $index => $media) {
                // Cas où chaque média est représenté comme un tableau associatif
                if (is_array($media)) {
                    // Sauvegarde la valeur de l'image (ou null si absente) pour cet index
                    $existingImages[$index] = $media['image'] ?? null;
                // Cas où chaque média est représenté comme un objet (au lieu d'un tableau)
                } elseif (is_object($media)) {
                    // Sauvegarde la valeur de l'image (ou null si absente) pour cet index
                    $existingImages[$index] = $media->image ?? null;
                }
            }
        }
    
         
        if ($form->isSubmitted() && $form->isValid()) {
   
            $formData = $form->getData();


            // Remplissage de l'objet avec les données du formulaire
            $deliveryTimes = [];

            foreach ($formData as $key => $value) {
                //specifique pour estimation de livraison
                if (strpos($key, 'deliveryTime_') === 0) {
                    $carrierId = (int) str_replace('deliveryTime_', '', $key);
                    $deliveryTimes[$carrierId] = (int) $value;
                } else {
                    $configObject->$key = $value;
                }
            }

            // injection specifique estimation de livraison 
            $configObject->deliveryTime = $deliveryTimes;

            // --- Cas spécifiques ---

        
            if(method_exists($configObject, 'enrich')) {
                // Si la méthode enrich existe, on l'appelle
                $configObject->enrich();
            }

            if(method_exists($configObject, 'copyCss')){
                $configObject->copyCss();
            }

            if(method_exists($configObject, 'fontUpdate')){
                $configObject->fontUpdate();
            }

            if(method_exists($configObject, 'injectIntoGroup')){
                $configObject->injectIntoGroup($config , $action, $id ,$group_id);
            }

            // Gestion d'image (optionnel)
            if ($upload) {
                 $uploadDir = _PS_ROOT_DIR_ . '/themes/presta_theme/assets/img';

                if ($formType === MenuMediaType::class) {
                    foreach ($form->get('medias') as $index => $mediaForm) {
                        $file = $mediaForm->get('image')->getData();

                        if ($file instanceof UploadedFile) {
                            $uploadDir = _PS_ROOT_DIR_ . '/themes/presta_theme/assets/img';
                            // ⚠️ Si $configObject->medias[$index] est un tableau, transforme-le en objet d'abord
                                $configObject->medias[$index]['image'] = ThemeTools::uploadImage($file, $uploadDir);

                        }else{//(aucun nouveau fichier n'a été uploadé pour ce média)
                            // On restaure l'image existante précédemment sauvegardée dans $existingImages
                            // ou on met null si aucune image n'existait
                            $configObject->medias[$index]['image'] = $existingImages[$index] ?? null;
                        }
                    }
                }else{
                    $file = $form->get('image')->getData();
                      if ($file instanceof UploadedFile) {
                        $configObject->image = ThemeTools::uploadImage($file, $uploadDir);
                       }else {
                        // Pas de nouveau fichier : on garde l'image actuelle
                        $configObject->image = $configObject->image ?? null;
                    }
                }
              
            }

         
        
            if ($menuColumn) {
                $configObject->injectInto($config->configMenuParent, isset($_GET['column']) ? $_GET['column'] : $id, $action);
            }

            // Sauvegarde
            $config->save();

            ThemeTools::updateCssFile();
        
            $this->addFlash('success', 'Vos paramètres ont bien été modifiés');

        
            if ($redirectRoute) {

                $params = [];
                

                // =========================
                // CAS 1 : on vient d'un ITEM
                // =========================
                if (method_exists($configObject, 'injectIntoGroup')) {
                    $params['group_id'] = $group_id;
                }

                // =========================
                // CAS 2 : on vient d'un GROUP
                // =========================
                elseif ($configObject instanceof AbstractGroup) {

                    $params['group_id'] = $configObject->id;

                    // Si le group fonctionne en "single item"
                    if (method_exists($configObject, 'hasSingleItemMode') && $configObject->hasSingleItemMode()) {

                        if (empty($configObject->items)) {
                            $params['action'] = 'add';
                            $params['id'] = 0;
                        } else {
                            $params['action'] = 'edit';
                            $params['id'] = $configObject->items[0]->id;
                        }
                    }
                }

                // =========================
                // CAS MENU (spécial parent)
                // =========================
                if ($objet === 'configMenuChild' || $objet === 'configMenuMedia') {
                    $params['parent_id'] = $parent_id;
                }

                return $this->redirectToRoute($redirectRoute, $params);
            }

        }else {
            foreach ($form->getErrors(true) as $error) {
                $field = $error->getOrigin()->getName(); // nom du champ (optionnel)
                $this->addFlash('error', sprintf("Erreur dans '%s' : %s", $field, $error->getMessage()));
            }
        }

        if(!$form->isSubmitted()){
            // Pré-remplissage pour affichage (parent ou brand)
            if ($configObject instanceof \PrestaShop\Module\LCVPrestaTheme\Config\ConfigBrand) {
                $configObject->selected_brands = !empty($configObject->selected_brands)
                    ? array_map(fn($b) => is_array($b) ? $b['id'] : $b, $configObject->selected_brands)
                    : [];
            }

            // Pré-remplissage pour deliveryTime
           if (property_exists($configObject, 'deliveryTime')) {
                foreach ($configObject->deliveryTime as $carrierId => $days) {
                    $configObject->{'deliveryTime_' . $carrierId} = $days;
                }
               
            }
           
            if ($formType === MenuParentType::class && isset($configObject->menu['id'])) {
                $configObject->menu = $configObject->menu['id'];
            }   

            
            $mediaImages = [];

            if (!empty($configObject->medias)) {
                foreach ($configObject->medias as $index => $media) {
                    if (!empty($media['image'])) {
                        $mediaImages[$index] = $media['image'];
                    }
                }
            }

        
            // Pré-remplir le formulaire avec l'objet
            $form->setData(get_object_vars($configObject));

        }

            // Affichage du formulaire
            return $this->render('@Modules/lcvprestatheme/views/templates/admin/configurateur.html.twig', [
                'form'  => $form->createView(),
                'title' => $title,
                'configImage' => !empty($configObject->image) ? $configObject->image : null,
                'mediaImages' => !empty($mediaImages) ? $mediaImages : [],
                'intro' => isset($intro) ? $intro : '',
                'url' =>  \Context::getContext()->shop->getBaseURL(),
            ]);
         
    }


    public function toggleVisibility(Request $request): JsonResponse
    {
        // Récupère l'identifiant du bloc ciblé (ex: "5", "test&", etc.)
        $id = $request->request->get('id');

        $columnIndex = $request->request->get('column');

        

        // Récupère le type d'objet à modifier
        $objet = $request->request->get('objet');

        // Charge la configuration JSON actuelle (config.json)
        $config = ConfigTheme::load();

        // Vérifie que l'objet existe bien dans le tableau (sinon on retourne une erreur 404)
        if (!isset($config->$objet[$id])) {
            return new JsonResponse(['success' => false, 'message' => 'Objet introuvable'], 404);
        }

        // Inverse l'état de visibilité (true devient false, false devient true)
        $config->$objet[$id]->isVisible = !$config->$objet[$id]->isVisible;

        // Sauvegarde la configuration modifiée dans le fichier JSON
      

        // Si l'objet (ex: ConfigMenuChild ou ConfigMenuMedia) possède la méthode injectInto()
        if (method_exists($config->$objet[$id], 'injectInto')) {  
            // Appelle injectInto pour mettre à jour le isVisible dans configMenuParent
            // - on utilise $_GET['column'] si fourni, sinon on prend $id par défaut
            $config->$objet[$id]->injectInto($config->configMenuParent,$columnIndex,"edit");
            
        }

        $config->save();
        

        // Renvoie une réponse JSON à l'appel AJAX avec le nouvel état
        return new JsonResponse([
            'success' => true,
            'new_state' => $config->$objet[$id]->isVisible,
        ]);
    }
}
