<?php

namespace PrestaShop\Module\PolarisPrestaTheme\Controllers\Admin;

use PhpParser\Node\Stmt\ElseIf_;
use PrestaShopBundle\Controller\Admin\PrestaShopAdminController;
use Symfony\Component\HttpFoundation\Request;
use PrestaShop\Module\PolarisPrestaTheme\Classes\ThemeTools;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use PrestaShop\Module\PolarisPrestaTheme\Config\ConfigTheme;
use PrestaShop\Module\PolarisPrestaTheme\Forms\{MenuParentType, MenuChildType, GeneralType, MenuMediaType, StoreInfoType, StoreType};
use Symfony\Component\HttpFoundation\JsonResponse;
use PrestaShop\Module\PolarisPrestaTheme\Classes\AbstractGroup;

/**
 * AdminFormController
 *
 * Contrôleur pour la gestion des formulaires du module PolarisPrestaTheme
 */
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');
                    }

                    if(method_exists($configObject, 'injectInto')){
                        $menuColumn = true;
                    }
                } 
                // sinon on utilise l'index classique
                else {

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

                    $configObject = $config->$objet[$id];
                 

                }
            }
            /*
            |--------------------------------------------------------------------------
            | 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;
                    }

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

                     // suppression colonne menu
                    if ($menuColumn) {
                        $configObject->injectInto(
                            $config->configMenuParent,
                            $action,
                            $request->query->has('column') ? (int) $request->query->get('column') : $id
                        );

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

                    }

                } 
                else {

                    $configObject = $config->$objet[$id];
                     
                    unset($config->$objet[$id]);

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

                   

                }

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

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

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

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

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

                        if ($file instanceof UploadedFile) {
                            // ⚠️ 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;
                        }
                    }
                  
                }elseif ($formType === MenuParentType::class && $configObject->menu['type'] == 'custom') {
                        $file = $form->get('image')->getData();
                        if($file != null){
                            $configObject->menu['image'] = ThemeTools::uploadImage($file, $uploadDir);
                        }


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

                    // Image mobile optionnelle (art direction) — même logique, uniquement
                    // pour les formulaires qui exposent ce champ (ex. slider).
                    if ($form->has('imageMobile')) {
                        $fileMobile = $form->get('imageMobile')->getData();
                        if ($fileMobile instanceof UploadedFile) {
                            $configObject->imageMobile = ThemeTools::uploadImage($fileMobile, $uploadDir);
                        } else {
                            // Pas de nouveau fichier : on conserve l'image mobile actuelle
                            $configObject->imageMobile = $configObject->imageMobile ?? null;
                        }
                    }
                }
              
            }

         
        
            if ($menuColumn) {
                $configObject->injectInto($config->configMenuParent, $action, $request->query->has('column') ? (int) $request->query->get('column') : $id);
                $configObject->parent_id = (int) $configObject->parent_id;
            }

     
             
            // 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\PolarisPrestaTheme\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;
                }
               
            }

            
      
           $menu_type = null;
            if ($formType === MenuParentType::class && isset($configObject->menu['id']) && $configObject->menu['type'] != 'custom') {
                $configObject->menu = $configObject->menu['id'];
                
            }elseif($formType === MenuParentType::class && isset($configObject->menu['id']) && $configObject->menu['type'] == 'custom'){
                //si menu parent custom
                 $menu_type = $configObject->menu['type'];
                 $configObject->image = $configObject->menu['image'];
                 $customName = $configObject->menu['name'] ?? '';
                 $customUrl  = $configObject->menu['url']  ?? '';
                 $configObject->menu = null; // ← évite le array to string
            }
            
            
            $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));

            // remplissage data menu parent custom
            if ($formType === MenuParentType::class &&  $menu_type == 'custom' ){
                $form->get('menu_type')->setData($menu_type);
                $form->get('custom_label')->setData($customName);
                $form->get('custom_url')->setData($customUrl);
                
            }

         


        }

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


    public function toggleVisibility(Request $request): JsonResponse
    {
        // Récupère l'identifiant du bloc ciblé (propriété "id" de l'objet de config)
        $id = $request->request->get('id');

        // Index de la colonne dans le menu parent (uniquement pour les sous-menus / médias)
        $columnIndex = $request->request->get('column');

        // Récupère le type d'objet à modifier (ex: configMenuParent, configMenuChild, configMenuMedia)
        $objet = $request->request->get('objet');

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

        // L'objet ciblé doit exister et être un tableau
        if (!property_exists($config, $objet) || !is_array($config->$objet)) {
            return new JsonResponse(['success' => false, 'message' => 'Objet introuvable'], 404);
        }

        // Recherche de l'élément ciblé.
        // Les objets de menu possèdent leur propre "id" : on cherche par id (cohérent
        // avec les actions edit/delete). Sinon, on retombe sur l'accès par index.
        $target = null;
        foreach ($config->$objet as $obj) {
            if (isset($obj->id) && (int) $obj->id === (int) $id) {
                $target = $obj;
                break;
            }
        }
        if ($target === null && isset($config->$objet[$id]) && !isset($config->$objet[$id]->id)) {
            $target = $config->$objet[$id];
        }

        if ($target === null) {
            return new JsonResponse(['success' => false, 'message' => 'Objet introuvable'], 404);
        }

        // Inverse l'état de visibilité (true devient false, false devient true)
        $target->isVisible = !$target->isVisible;

        // Si l'objet (ex: ConfigMenuChild ou ConfigMenuMedia) possède injectInto(),
        // on répercute le nouvel état dans la colonne du menu parent.
        if (method_exists($target, 'injectInto')) {
            $target->injectInto(
                $config->configMenuParent,
                'edit',
                $columnIndex !== null ? (int) $columnIndex : null
            );
        }

        $config->save();

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