import React, {Component} from 'react';
import './QuestionBox.css';
// import Prism from "prismjs";
// import 'prismjs/themes/prism.css';
// Import de Prism de base
import Prism from 'prismjs';

// Import des langages
import 'prismjs/components/prism-markup';  // HTML, XML
import 'prismjs/components/prism-css';     // CSS

// Import des plugins
import 'prismjs/plugins/inline-color/prism-inline-color.js';
import 'prismjs/plugins/inline-color/prism-inline-color.css';

// import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/toolbar/prism-toolbar.min.css';
import 'prismjs/plugins/toolbar/prism-toolbar.min.js';
import 'prismjs/plugins/download-button/prism-download-button.js';
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js';
import 'prismjs/plugins/show-language/prism-show-language.js';

// src/QuestionBox.js

import { saveAs } from 'file-saver';


Prism.hooks.add('wrap', function (env) {
    // Ajoutez les types de tokens que vous voulez cibler
    if (env.type === 'keyword' || env.type === 'attr-name') {
        env.classes.push('keyword-' + env.content);
    }
});

const currentPath = window.location.pathname;

if (currentPath != "/" && !window.scriptHtmlInfosLoaded) {
    setTimeout(() => {
        // alert("outscript")
        console.log('Exécution après le rendu');
        fetch('/script_html_infos.js')
            .then(response => response.text())
            .then(scriptContent => {
                const script = document.createElement('script');
                script.textContent = scriptContent;
                document.body.appendChild(script);
                window.scriptHtmlInfosLoaded = true; // Marquer le script comme chargé
            })
            .catch(error => {
                console.error('Erreur lors du chargement du script:', error);
            });
    }, 10);


    const script = document.createElement('script');
    script.src = "/code_textarea_update.js"; // Replace with your script path
    script.async = true;

    // Append the script to the body (footer)
    document.body.appendChild(script);      


    window.clonecode = clonecode;
    function clonecode() {
        // alert("clic")
        $(".code-content").clone().addClass("fullscreen_codecontent").appendTo("body");
        $(".code-content:not(.fullscreen_codecontent)").removeClass("code-content").addClass("original_codecontent")
      }

    window.getCodeContent_thenSave = getCodeContent_thenSave;
    function getCodeContent_thenSave(file_path, fileName, uniqueId_state, saveto, datatype) {
        // alert(saveto +" =+= "+ fileName)
        const codeElement = document.querySelector(`code[data-filename="${fileName}"]`);

        console.warn("----- GO saveDataToServer = FileName == "+fileName)

        if (codeElement) {
            
            console.log("--- Changed == "+fileName)
            let innerHTML_pls = $(codeElement).text();
            // alert(innerHTML_pls)
            // let innerHTML_pls = codeElement.innerHTML.replace(/<[^>]*>/g, ''); /// good old
            // let innerHTML_pls = codeElement.innerHTML;
            
            if (saveto=="satofile") {
                console.log("----- satofile")
                saveDataToFile(innerHTML_pls, fileName, uniqueId_state,saveto)    
            } else  if (saveto!="direct") {
                console.log("----- Send to func saveDataToServer")
                saveDataToServer(innerHTML_pls, file_path, fileName, uniqueId_state,saveto)    
            
            } else  if (saveto=="direct") {
                // alert("direct ------ button")
                console.log("----- Send to func saveDataToServer")
                saveDataToServer(innerHTML_pls, file_path, fileName, uniqueId_state,saveto)    
            }
            
        } else {
            console.error("----- ERRORS saveDataToServer = FileName == "+fileName)
            return null;
        }
    }



    function saveDataToServer(datatos, filepath, fileName, uniqueId_state, saveto) {
        // alert(saveto)
        console.log("-------- data saveDataToServer ---- ")
        console.log("saveDataToServer == ", filepath, fileName, uniqueId_state)
        const url = "/api/savefile";
        const response = fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ datatos, filepath, fileName, uniqueId_state, saveto }),
        });

        const hostname=window.location.hostname
        const fixpagename_html = fileName.replace(".page",".html")
        if (saveto=="direct") {
            alert("https://"+hostname+filepath+ "/data/"+ uniqueId_state+ "_"+ fixpagename_html+"\n\nCharger : \n"+uniqueId_state+ "_"+ fixpagename_html)
        }

        const result = response;
        console.log(result);
    }
    


    function saveDataToFile(datatofile, fileName, uniqueId_state) {
        const fixpagename_html = fileName.replace(".page",".html")
        const blob = new Blob([datatofile], { type: 'text/plain;charset=utf-8' });
        saveAs(blob, uniqueId_state+"__"+fixpagename_html);
    }

    // Attach the function to the window object
    // window.saveDataToFile = saveDataToFile;

// Source - https://stackoverflow.com/a
// Posted by Blowsie, modified by community. See post 'Timeline' for change history
// Retrieved 2025-11-15, License - CC BY-SA 3.0


} /// IF Not HOME











class QuestionBox extends Component {
    state = {
        value: '',
        additionalInput: '',
        uniqueIdInput: '',
        answersData: [],
        loadedHtml: '',
        textareaValues: {},
        txtContents: {},
        showTOC: false, // État pour afficher/masquer la TOC
        file_to_load: null, // Nouvelle variable pour stocker le nom du fichier à charger
    };

    // Méthode pour basculer l'affichage de la TOC
    toggleTOC = () => {
        this.setState(prevState => ({
            showTOC: !prevState.showTOC
        }));
    };

    handleLoadFilePrompt = (e) => {
        // Conserver l'événement ou extraire les informations nécessaires immédiatement
        e.persist(); // Conserve l'événement synthétique

        const fileName_raw = prompt("Entrez le nom du fichier à charger :");
        const currentPath = window.location.pathname;
        let fileName = fileName_raw;

        if (fileName) {
            const data_file = currentPath + "/data/" + fileName;
            // Trouver l'élément parent du bouton cliqué
            const button = e.currentTarget;
            console.log(e)
            const codeElement = $(button).parent().parent('.prewrap').find('code[data-filename]');

            this.setState({ file_to_load: data_file }, async () => {
                try {
                    const content = await this.fetch_file_content(data_file);
                    if (codeElement) {
                        // alert("codeElement ==== " +$(codeElement).attr("class"))
                        // Mettre à jour le contenu de l'élément <code>
                        // codeElement.textContent = content;

                        // Mettre à jour la valeur du textarea associé (si nécessaire)
                        $(codeElement).attr("data-filename",fileName);

                        const textareaElement = $(button).parent().next('textarea');
                        // alert(textareaElement.length)

                        $(textareaElement).remove();
                        $(button).parent().after("<textarea id='editing'></textarea>")
                        const textareaElement_new =  $(button).parent().parent().find("textarea")
                        // alert(textareaElement_new.length)
                        
                        if (textareaElement_new) {
                            // alert("textareaElement_new")
                            $(textareaElement_new).attr("data-filename",fileName);
                            $(textareaElement_new).val(content);
                            
                            setTimeout(() => {
                                // Mettre à jour textareaValues dans l'état
                                this.setState(prevState => ({
                                    textareaValues: {
                                        ...prevState.textareaValues,
                                        [fileName]: content
                                    }
                                }));

                                let language;
            
                                switch (true) {
                                  case fileName.includes("css"):
                                    language = "css";
                                    break;
                                  case fileName.includes("js"):
                                    language = "js";
                                    break;
                                  case fileName.includes("html"):
                                    language = "markup";
                                    break;
                                  case fileName.includes("markup"):
                                    language = "markup";
                                    break;
                                  default:
                                    language = "plaintext";
                                }

                                // Appeler updateCodeContent pour synchroniser le code
                                this.updateCodeContent(fileName, content, language);
                                this.updateTextareaHeight(fileName)

                            }, 1200);
                        }


                    }
                } catch (error) {
                    console.error("Erreur lors du chargement du fichier :", error);
                }
            });
        }
    };

    // Méthode pour gérer la saisie de l'ID unique
    handleUniqueIdChange = (event) => {
        this.setState({ uniqueIdInput: event.target.value });
    };

    // Méthode pour gérer la saisie du champ supplémentaire
    handleAdditionalInputChange = (event) => {
        this.setState({ additionalInput: event.target.value });
    };

    // Méthode pour déclencher getAnswers avec l'ID saisi
    handleUniqueIdSubmit = (event) => {
        event.preventDefault();
        const { uniqueIdInput } = this.state;
        if (uniqueIdInput.trim()) {
            this.getAnswers(uniqueIdInput.trim());
        } else {
            alert("Veuillez entrer un ID unique valide.");
        }
    };
    

    //// Textaarea update
    updateCodeContent(fileName, newValue, codeItem_type) {

        const codeElement = document.querySelector(`code[data-filename="${fileName}"]`);
        const tareaElement = document.querySelector(`textarea[data-filename="${fileName}"]`);

        // console.log(newValue.length )

        if (codeElement) {
            codeElement.classList.add('changed_code_element');
            // Ajouter un texte de substitution si newValue est vide
            if (newValue.length === 0) {
                let placeholderText = "";
                if (codeItem_type === "css") {
                    placeholderText = "/* Écrivez votre code CSS ici */";
                } else if (codeItem_type === "markup") {
                    placeholderText = "<!-- Écrivez votre code HTML ici -->";
                } else if (codeItem_type === "javascript") {
                    placeholderText = "// Écrivez votre code JavaScript ici";
                } else {
                    placeholderText = "// Écrivez votre code ici";
                }
                codeElement.textContent = placeholderText;
                tareaElement.value = placeholderText;
                
                // alert("00")

            } else {
                codeElement.textContent = newValue;
            }
        }
        Prism.highlightElement(codeElement); // Reapplique la coloration syntaxique

        // Défilement vers le haut de la page
        // window.scrollTo(0, 0);

        if (codeItem_type=="css") {
            let css_count=0;
            
            $('code.language-css').each(function() {
                css_count++;
                $(this).attr("data-num_css", css_count)
                var codeContent = $(this).text();
                let this_data_name = $(this).attr("id");
                let this_projet = $(this).attr("data-projet");
                let dataname = (this_data_name!=undefined) ? this_data_name : $(this).attr("data-filename");
                const timestamp = Date.now();
                $('style[css_count]').remove();
                $('<style css_count="'+css_count+'_'+dataname+'" data-js="update" date-timestamp="'+timestamp+'">div.codeContent_wrapper[data-projet="'+this_projet+'"] { '+codeContent+' }</style>').appendTo('head');
            }); /// EACH LAnguades    

        } else if (codeItem_type=="markup") {
            // alert("markup")
            const currentPath= window.location.pathname;
            // context : update
            // path fix ./ img/content 
            var codeContent = $(codeElement).text().replace(/\.\//g, "/codes"+currentPath+"/");
            // alert(codeContent)
            $(".codeContent_wrapper").html(codeContent)
        }

        if (newValue.length != 0) {
            this.updateTextareaHeight(fileName)
        }
        
    }

    updateTextareaHeight(fileName) {
        const codeElement = document.querySelector(`code[data-filename="${fileName}"]`);
        const textareaElement = document.querySelector(`textarea[data-filename="${fileName}"]`);

        if (codeElement && textareaElement) {
            textareaElement.style.height = `calc(${codeElement.offsetHeight}px + 50px)`;
            textareaElement.style.marginBottom = `calc(-${codeElement.offsetHeight}px - 100px)`; // Correction de la syntaxe
        }
    }

    escapeHtml(str) {
        return str
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }

    escapeCodeScapeElements() {
        const elements = document.querySelectorAll('codescape');
        elements.forEach(el => {
            const rawContent = el.innerHTML;
            // const rawType = $(el).attr("class");
            const escapedContent = this.escapeHtml(rawContent);

            const rawType = $(el).attr("class");
            let language;
            
            switch (true) {
              case rawType.includes("css"):
                language = "language-css";
                break;
              case rawType.includes("js"):
                language = "language-js";
                break;
              case rawType.includes("html"):
                language = "language-markup";
                break;
              case rawType.includes("markup"):
                language = "language-markup";
                break;
              default:
                language = rawType;
            }
            let languageonly
            switch (true) {
                case rawType.includes("css"):
                  languageonly = "css";
                  break;
                case rawType.includes("js"):
                  languageonly = "js";
                  break;
                case rawType.includes("html"):
                  languageonly = "html";
                  break;
                case rawType.includes("markup"):
                  languageonly = "html";
                  break;
                default:
                  languageonly = "";
              }
            
            // console.log(language);
            

            // Créer un nouvel élément code avec la classe désirée, ici language-markup
            const codeEl = document.createElement('code');
            codeEl.className = language +" codescaped " +rawType;
            codeEl.setAttribute("data-type", languageonly);
            // alert(escapedContent)
            codeEl.innerHTML = escapedContent.replace(/&amp;gt;/g, ">").replace(/^\s+/g, "");

            // Remplacer l'élément codescape original par code
            el.parentNode.replaceChild(codeEl, el);
        });
    }

    componentDidMount() {
        const searchParams = new URLSearchParams(window.location.search);
        const idParam = searchParams.get('id');
        const questionParam = searchParams.get('question');
        const storedUniqueId = localStorage.getItem('uniqueId');

        if (questionParam) {
            const questionIndex = parseInt(questionParam, 10);
            if (!isNaN(questionIndex) && questionIndex >= 1 && questionIndex < this.props.state.config.questions.length+1) {
                this.props.api.updateState({
                    currentQuestionIndex: questionIndex+1,
                    question: this.props.state.config.questions[questionIndex]
                });
            }

            // alert("mounted")
            this.applyScripts();




        }
    

        this.loadAllCodeFiles();
    
        const uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);
        this.setState({ uniqueId: uniqueId });
        if (idParam && !questionParam) {
            this.setState({ uniqueIdInput: idParam }, () => {
                this.handleUniqueIdSubmit({ preventDefault: () => {} });
            });
        } else if (storedUniqueId) {
            this.setState({ uniqueIdInput: storedUniqueId });
        }

        // Si un paramètre "question" est présent, mettre à jour l'index de la question courante

        setTimeout(() => {


            if (this.props.state.question && this.props.state.question.code) {
                this.props.state.question.code.forEach(codeItem => {
                    this.updateTextareaHeight(codeItem.file);
                    if (codeItem.type === "txt") {
                        this.fetch_file_content(codeItem.file).then(content => {
                            this.setState(prevState => ({
                                txtContents: {
                                    ...prevState.txtContents,
                                    [codeItem.file]: content
                                }
                            }));
                        });
                    }
                });
            }
        }, 900);
    
        window.scrollTo(0, 0);
    
        // Sélectionner tous les éléments avec la classe "prewrap"
        const elements = document.querySelectorAll('.prewrap');
    
        if (elements.length > 0) {
            // Créer la div qui va envelopper tous les éléments
            const wrapper = document.createElement('div');
            wrapper.id = 'wrap_allprewrap';
            wrapper.clas = 'clearix';
    
            // Prendre l'élément parent commun (assumons ici que tous ont le même parent)
            const parent = elements[0].parentNode;
    
            // Insérer le wrapper avant le premier élément .prewrap
            parent.insertBefore(wrapper, elements[0]);
    
            // Déplacer tous les éléments .prewrap dans le wrapper
            elements.forEach(el => wrapper.appendChild(el));
        }

    }

    
    componentDidUpdate(prevProps, prevState) {
    
                


        // Charger les fichiers si la question change
        if (prevProps.state.question !== this.props.state.question) {
            this.loadAllCodeFiles();
        }
        
        if (prevState.loadedHtml !== this.state.loadedHtml) {
            this.escapeCodeScapeElements(); // Appel avant applyPrismHighlighting
            this.applyPrismHighlighting();
            this.applyScripts();
        }
        setTimeout(() => {
            window.scrollTo(0, 0);

        }, 1000);
    
        
    }
    
    async fetch_file_content(fileName) {
        // alert("fetch_file_content")
        // console.warn("fetch_file_content GO")
        // console.warn("fileName ====== "+fileName)
        const currentPath= window.location.pathname;

        if (currentPath=="/") {
            var sub_folder=""
        } else {
            var sub_folder=currentPath+"/"
            console.warn("sub_folder async "+sub_folder)
        }

        try {
            // Ensure the file path is correct and not being intercepted by React's routing
            const response = await fetch(`/codes/${fileName}`);
            console.log("\n\n\n\n------------------- response")
            console.log(response)
            
            if (!response.ok) throw new Error('Network response was not ok');
            
            const text = await response.text();
            console.log("\n\n\n\n------------------- text")
            // console.log(text)
            // console.log(`Contenu du fichier ${fileName}:`, text);
            console.warn("fetch_file_content END")
            return text;

        } catch (error) {
            console.error(`Erreur lors du chargement du fichier ${fileName}:`, error);
            console.warn("ERROR fetch_file_content END")
            return '';
        }
    }

    loadAllCodeFiles() {
        if (!this.props.state.question || !this.props.state.question.code) return;
        


        const searchParams = new URLSearchParams(window.location.search);
        const idParam = searchParams.get('id');
        const questionParam = searchParams.get('question');
        const storedUniqueId = localStorage.getItem('uniqueId');

        if (questionParam) {
            const questionIndex = parseInt(questionParam, 10);
            if (!isNaN(questionIndex) && questionIndex >= 1 && questionIndex < this.props.state.config.questions.length+1) {
                this.props.api.updateState({
                    currentQuestionIndex: questionIndex,
                    question: this.props.state.config.questions[questionIndex]
                });
            }
            
        }

        const loadedContent = {};
        const codeFiles = this.props.state.question.code;
        const currentPath = window.location.pathname;
        
        if (currentPath=="/") { 
            var sub_folder=""
        } else {
            var sub_folder=currentPath+"/"
            console.warn("sub_folder "+sub_folder)
        }
        console.log("codeFiles ----- ")
        console.log(codeFiles)
        let filteredData_id = null;
        let filteredData_code = null;
        
        /// GET jsondata (no api) 
        if (idParam) {
            const jsonData = require('./data.json');
            // UNIQUE id
            const filteredData = jsonData.filter(item => item.uniqueId === idParam);
            if (filteredData.length === 0) {
                console.error(`Aucune entrée trouvée avec l'uniqueId: ${idParam}`);
            } else {
                console.warn("// uniqueId filteredData OK (read, loaded)")
                let idpls = this.props.state.question.id
                var filteredData_awnsers = filteredData[0].answers /// .awnsers
                /// FILTRE awnsers w/ id==idpls
                filteredData_id = filteredData_awnsers.filter(item => item.id === idpls);
                
                // Vérifier que filteredData_id[0] existe avant d'accéder à .code
                if (filteredData_id.length > 0 && filteredData_id[0].code) {
                    /// .code
                    filteredData_code = filteredData_id[0].code
                }
            }

            console.warn("// filteredData_existe loadAllCodeFiles")
            console.warn(filteredData_code)






            // https://claude.ai/chat/2ae39a55-5879-4427-b4c9-af7ddff13a23
            /// Replace.Map Files of the page ( current question ) ... by modifed files (awnsers from data.json)
            if (filteredData_code && Array.isArray(filteredData_code)) {
                for (const file of codeFiles) {
                    const match = filteredData_code.find(codeItem => 
                        /// modified == le nom du fichier original !
                        //// chercher si Modified =egal.est= celui dans la liste à charger (codeFiles)
                        /// Si c'est le cas, cela veut dire que le fichier d'oridne a été modifié 
                        codeItem.modified === file.file
                    );
                    
                    if (match) {
                        //// si le fichier modifié (dans data.json) correspond au fichier à charger (de base)
                        //// chargé plus bas avec 
                        ///// ///    Promise.all( codeFiles.map(codeItem => ....
                        console.log(`Trouvé: ${file.file}`, match.file);
                        // Remplacer la valeur de file par match.file
                        /// On retir /"exemple"/data/file exemple ... retrouvé plus tard par l'id du questionnaire
                        var fixpath= "/" + match.file.split("/").slice(2).join("/");
                        /// codeItem (file) > file est remplacé par fixpath ( le fichier modifié )
                        file.file = fixpath;
                    }
                }
            } else {
                console.log('filteredData_code n\'existe pas ou n\'est pas un tableau');
            }
            
            console.log('codeFiles modifié:', codeFiles);
        }
        


        Promise.all(
            codeFiles.map(codeItem =>
                fetch(`/codes/${sub_folder}${codeItem.file}`)
                .then(response => {
                    if (!response.ok) throw new Error('Network response was not ok');
                    console.log("----------------------\n--- 1 "+codeItem.file)

                    return response.text();
                })
                .then(content => {
                    // console.log("--- 2 "+codeItem.file)
                    loadedContent[codeItem.file] = content;
                    // console.log(content)
                    console.log("----------------------END")
                    this.setState({ contentfile: content, content });
                })
                .catch(error => {
                    console.error(`Erreur lors du chargement du fichier ${codeItem.file}:`, error);
                    loadedContent[codeItem.file] = '';
                })
            )
        ).then(() => {
            this.setState({ loadedHtml: loadedContent, loadedContent });

        });
    }

    applyPrismHighlighting() {
        setTimeout(() => {
            Prism.highlightAll();
        }, 400);    
    }
 

    renderTOC = () => {
        const { questions } = this.props.state.config;
        const currentQuestionIndex = this.props.state.currentQuestionIndex;
        const searchParams = new URLSearchParams(window.location.search);
        const idParam = searchParams.get('id');
        let addidParam = (idParam) ? "&id="+idParam : "";
        return (
            <div className="toc-container">
                <h2>Table des matières</h2>
                <ul className="toc-list">
                    {questions.map((question, index) => (

                        <li
                            key={index}
                            className={currentQuestionIndex === index ? 'active' : ''}
                        >
                            <span>{index}. </span>
                            
                            <a
                                title={question.id}
                                href={`?question=${index}${addidParam}`}
                                onClick={(e) => {
                                    e.preventDefault();
                                    if ($(".changed_code_element").length > 0) {
                                        if (window.confirm("Un contenu a été modifié...\nen quittant cette page il va être perdu ! \nContinuer ?")) {
                                            window.location.search = `?question=${index}${addidParam}`;
                                          }                                          
                                    }
                                    window.location.search = `?question=${index}${addidParam}`;
                                }}
                            >
                                {question.title}
                            </a> <span className='toc_shortname'>{question.short}</span>
                            <span className='toc_idname idname'>{question.id}</span>
                        </li>
                    ))}
                </ul>
            </div>
        );
    }
    force_applyScripts() {
        let css_count = 0;
        $('code.language-css').each(function() {
            css_count++;
            // alert("kk")
            $(this).attr("data-num_css", css_count)
            var codeContent = $(this).text();
            let this_data_name = $(this).attr("id");
            let this_projet = $(this).attr("data-projet");
            let dataname = (this_data_name!=undefined) ? this_data_name : $(this).attr("data-filename");
            $('<style css_count="'+css_count+'_'+dataname+'" data-js="apply">div.codeContent_wrapper[data-projet="'+this_projet+'"] { '+codeContent+' }</style>').appendTo('head');
        }); /// EACH LAnguades


    }

applyScriptsnormcss() {

    // $("[css_count]").remove()


        
        this.escapeCodeScapeElements()
        
        var coll = document.getElementsByClassName("collapsible");
        var i;
        for (i = 0; i < coll.length; i++) {
            coll[i].addEventListener("click", function() {
                this.classList.toggle("active");
                var content = $(this).parent("p").next(".coll_content");
                $(content).toggleClass("active");
            });
        }

        // alert("applyScriptsnormcss")

    setTimeout(() => {

            $("#codecontent_all").remove()
            // alert($("#codecontent_all").length)

            $('pre code[class*="language-markup"]').each(function() {
                let data_filename=$(this).attr("data-filename")
                let data_projet=$(this).attr("data-projet")
                const currentPath= window.location.pathname;
                // path fix ./ img/content
                var codeContent = $(this).text().replace(/\.\//g, "/codes"+currentPath+"/");
                // var codeContent = $(this).text();
                // alert("codeContent "+codeContent)
                if ( $(this).hasClass("nohelp_result") ) {
                    // console.log("nohelp_result")
                    // alert("nohelp_result")
                }
                else if ( !$(this).hasClass("nohelp") || $(".is_awnsers_show_me_help").length==1 ) {
                    // alert("gooo")
                    
                    $(this).parent('pre:not(.nohelp_result, .nohelp)')
                    .after(`<div id="codecontent_all">
                                <input type="checkbox" class="checkbox_minimize_code" id="minimize_code" />
                                <label for="minimize_code"></label>
                                <input type="checkbox" class="checkbox_maximize_code" id="maximize_code" />
                                <label for="maximize_code"></label>
                                <div class="code-content">
                                    <span id="codeContent_label">Rendu :</span>
                                    <div class="codeContent_wrapper" data-projet="`+data_projet+`" data-filename="` +data_filename+ `">` + codeContent + `</div>
                                </div>
                            </div>
                            `);
                }
            });
        }, 600);
    
}

    applyScripts() {


        var coll = document.getElementsByClassName("collapsible");
        var i;
        for (i = 0; i < coll.length; i++) {
        coll[i].addEventListener("click", function() {
            this.classList.toggle("active");
            var content = this.nextElementSibling;
            if (content.style.display === "block") {
            content.style.display = "none";
            } else {
            content.style.display = "block";
            }
        });
        } 

        $("[css_count]").remove()

        setTimeout(() => {

            // alert("applyScripts")

            let html_count=0;
            if ($("#codecontent_all") && $(".is_awnsers_show_me_help").length !== 1) { $("#codecontent_all").remove() }
        


            $('pre code[class*="language-markup"]').each(function() {
                let data_filename=$(this).attr("data-filename")
                let data_projet=$(this).attr("data-projet")
                const currentPath= window.location.pathname;
                // path fix ./ img/content
                var codeContent = $(this).text().replace(/\.\//g, "/codes"+currentPath+"/");
                // var codeContent = $(this).text();
                // alert("codeContent "+codeContent)
                if ( $(this).hasClass("nohelp_result") ) {
                    // console.log("nohelp_result")
                    // alert("nohelp_result")
                }
                else if ( !$(this).hasClass("nohelp") || $(".is_awnsers_show_me_help").length==1 ) {
                    // alert("gooo")
                    
                    $(this).parent('pre:not(.nohelp_result, .nohelp)')
                    .after(`<div id="codecontent_all">
                                <input type="checkbox" class="checkbox_minimize_code" id="minimize_code" />
                                <label for="minimize_code"></label>
                                <i class="material-icons butr open_in_full">open_in_full</i>
                                <input type="checkbox" class="checkbox_maximize_code" id="maximize_code" />
                                <label for="maximize_code"></label>
                                <i class="material-icons butr maximize">maximize</i>
                                <div class="code-content">
                                    <span id="codeContent_label">Rendu :</span>
                                    <div class="codeContent_wrapper" data-projet="`+data_projet+`" data-filename="` +data_filename+ `">` + codeContent + `</div>
                                </div>
                            </div>
                            `);
                }


                $('.code-content').append(infoBox);


                // Récupération des éléments d'affichage
                const elementInfo = document.getElementById('element-info');
                const elementParent = document.getElementById('element-parent');
                const toggleCheckbox = document.getElementById('toggle-display');
                const infoContent = document.getElementById('info-content');
                
                if (infoContent) {
                    // Clé pour le localStorage
                    const STORAGE_KEY = 'info-box-hidden-state';

                    // Fonction pour appliquer l'état
                    function applyToggleState(isHidden) {
                        if (isHidden) {
                            infoContent.classList.add('hidden');
                            infoBox.classList.add('no_infos');
                            toggleCheckbox.checked = true;
                        } else {
                            infoContent.classList.remove('hidden');
                            infoBox.classList.remove('no_infos');
                            toggleCheckbox.checked = false;
                        }
                    }
                    /////////////////////////////////////////
                    /////////////////////////////////////////
                    //////   SAVE CHECKBOX STATES   /////////
                    /////////////////////////////////////////
                    /////////////////////////////////////////
                    // Charger l'état depuis localStorage au démarrage
                    const savedState = localStorage.getItem(STORAGE_KEY);
                    if (savedState !== null) {
                        applyToggleState(savedState === 'true');
                    }

                    // Gestion du toggle
                    toggleCheckbox.addEventListener('change', function() {
                        const isHidden = this.checked;
                        applyToggleState(isHidden);
                        // Sauvegarder l'état dans localStorage
                        localStorage.setItem(STORAGE_KEY, isHidden);
                    });
                }


                $( document ).ready(function() {
                    // Clé pour stocker les états dans localStorage
                    const STORAGE_KEY_ALL = 'checkboxStates';

                    // Fonction pour sauvegarder l'état de toutes les checkboxes
                    function saveAllCheckboxStates() {
                        const checkboxes = document.querySelectorAll('input[type="checkbox"]');
                        const states = {};
                        // alert("saveAllCheckboxStates")
                        checkboxes.forEach(checkbox => {
                            // if (checkbox.getAttribute("id","toggle-display")) return;
                            states[checkbox.id] = checkbox.checked;
                        });

                        localStorage.setItem(STORAGE_KEY_ALL, JSON.stringify(states));
                    }

                    // Fonction pour appliquer l'état sauvegardé à toutes les checkboxes
                    function applyToggleState() {
                        const savedState = localStorage.getItem(STORAGE_KEY_ALL);
                        // console.error("savedState === "+savedState)
                        if (savedState) {
                            const states = JSON.parse(savedState);
                            const checkboxes = document.querySelectorAll('input[type="checkbox"]');

                            checkboxes.forEach(checkbox => {
                                if (states[checkbox.id] !== undefined) {
                                    checkbox.checked = states[checkbox.id];
                                    // alert("LLLO")
                                }
                            });
                        }
                    }

                    // Écouter les changements sur toutes les checkboxes
                    document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
                        checkbox.addEventListener('change', saveAllCheckboxStates);
                    });

                    // Charger l'état sauvegardé au démarrage
                    window.addEventListener('DOMContentLoaded', applyToggleState);

                    applyToggleState()
                });


                
                if (infoContent) {
                
                
                    // Écouter l'événement mouseover sur tout le document
                    document.addEventListener('mouseover', function(e) {
                        const el = e.target;
                        
                        // Ignorer la boîte d'info elle-même
                        if (el.closest('#info-box')) {
                            return;
                        }
                        
                        // Récupérer les informations
                        const tag = el.tagName.toLowerCase();
                        const id = el.id;
                        const classes = el.className;
                        
                        // Construire la chaîne au format element#id.class
                        let infoStr = '<span class="info_prop info_el">' + tag + '</span>'; 
                        if (id) {
                            infoStr += '<span class="info_prop info_id">#' + id + '</span>';
                        }
                        if (classes) {
                            // Remplacer les espaces par des points pour les classes multiples
                            infoStr += '<span class="info_prop info_class">.' + classes.trim().replace(/\s+/g, '.') + '</span>';
                        }
                        
                        // Construire la chaîne parent au format element#id.class
                        let parentStr = '(aucun)';
                        if (el.parentElement) {
                            const parentTag = '<span class="info_prop info_el">'+ el.parentElement.tagName.toLowerCase() + '</span>';
                            const parentId = el.parentElement.id;
                            const parentClasses = el.parentElement.className;
                            
                            parentStr = parentTag;
                            if (parentId) {
                                parentStr += '<span class="info_prop info_id">#' + parentId + '</span>';
                            }
                            if (parentClasses) {
                                parentStr += '<span class="info_prop info_class">.' + parentClasses.trim().replace(/\s+/g, '.') + '</span>';
                            }
                        }
                        
                        // Afficher les informations
                        elementInfo.innerHTML = infoStr;
                        elementParent.innerHTML = parentStr;
                        
                        // Rendre la boîte visible
                        infoBox.classList.add('visible');
                    });
                
                    // Optionnel : cacher la boîte quand on quitte la page
                    document.addEventListener('mouseout', function(e) {
                        if (e.relatedTarget === null) {
                            infoBox.classList.remove('visible');
                        }
                    });
                
                } /// if infocontent (exists)

            }); /// EACH language-markup
        


            $('pre code[class*="language"]').each(function() {
                html_count++;
                $(this).attr("data-num_html", html_count)
                var classpls = $(this).attr("class");
                $(this).parent().parent().attr("data-type",classpls).parent().attr("data-type",classpls)
            }); //// EACH Code *language
        
        
            let css_count=0;
            $('code.language-css').each(function() {
                css_count++;
                $(this).attr("data-num_css", css_count)
                var codeContent = $(this).text();
                let this_data_name = $(this).attr("id");
                let this_projet = $(this).attr("data-projet");
                let dataname = (this_data_name!=undefined) ? this_data_name : $(this).attr("data-filename");
                // alert(this_data_name)
                // alert(dataname)
                // $('[css-count="'+css_count+'_'+dataname+'"]').remove();
                $('style[css_count]').remove();
                $('<style css_count="'+css_count+'_'+dataname+'" data-js="apply">div.codeContent_wrapper[data-projet="'+this_projet+'"] { '+codeContent+' }</style>').appendTo('head');
            }); /// EACH LAnguades

            // window.scrollTo(0, 0);


            // Sélectionner tous les éléments avec la classe "prewrap"
            const elements = document.querySelectorAll('.prewrap');

            if (elements.length > 0) {
                // Créer la div qui va envelopper tous les éléments
                const wrapper = document.createElement('div');
                wrapper.id = 'wrap_allprewrap';
                wrapper.clas = 'clearix';

                // Prendre l'élément parent commun (assumons ici que tous ont le même parent)
                const parent = elements[0].parentNode;

                // Insérer le wrapper avant le premier élément .prewrap
                parent.insertBefore(wrapper, elements[0]);

                // Déplacer tous les éléments .prewrap dans le wrapper
                elements.forEach(el => wrapper.appendChild(el));
            }
            

        }, 600);
        
            
        setTimeout(() => {
            // console.log('Exécution après le rendu');
            fetch('/wrap_css_html_copy.js')
                .then(response => response.text())
                .then(scriptContent => {
                    const script = document.createElement('script');
                    script.textContent = scriptContent;
                    document.body.appendChild(script);
                })
                .catch(error => {
                    console.error('Erreur lors du chargement du script:', error);
                });

                

        }, 300);   

 

// https://claude.ai/share/3ff7317d-6327-401e-844d-7b7a1f0f9dd4
let css_count = 0;
let prismTimeout = null; // Variable pour stocker le timeout de Prism
let isPrismRunning = false; // Flag pour savoir si Prism est en cours d'exécution

var editable = document.querySelectorAll('code[contentEditable]');
for (var i = 0, len = editable.length; i < len; i++) {
    // editable[i].setAttribute('data-orig', editable[i].innerHTML);

    editable[i].onkeyup = function(event) {

        // if (this.innerHTML == this.getAttribute('data-orig')) {
        //     // no change
        // }
        // else {
            // change has happened, store new value
            // this.setAttribute('data-orig', this.innerHTML);
            // const code_tocopy = $(this).text();
            // Nettoyer le contenu en supprimant les éléments indésirables
            // const tempDiv = document.createElement('div');
            // tempDiv.innerHTML = code_tocopy;
            // Supprimer les éléments indésirables
            // const unwantedSpans = tempDiv.querySelectorAll('span.line-numbers-rows, span[aria-hidden="true"]');
            // unwantedSpans.forEach(span => span.remove());
            // Récupérer le contenu nettoyé
            // const cleanedCode = tempDiv.innerHTML;

            // Trouver le textarea associé via data-filename
            // const filename = this.getAttribute("data-filename");
            // const associatedTextarea = document.querySelector(`textarea[data-filename="${filename}"]`);

            // if (associatedTextarea) {
                $(this).parent().addClass("changed_code_element"); //// BUGfix cant be code... doit on parent
                // associatedTextarea.value = cleanedCode;
                
                let textonly = $(this).text();
                
                // Sauvegarder la position absolue du caret (en nombre de caractères)
                var sel = window.getSelection();
                var range = sel.getRangeAt(0);
                var preCaretRange = range.cloneRange();
                preCaretRange.selectNodeContents(this);
                preCaretRange.setEnd(range.endContainer, range.endOffset);
                var caretPos = preCaretRange.toString().length;
                
                console.log("Caret position (chars from start):", caretPos);
                
                if (this.getAttribute("class").includes('language-markup')) { //// HTML
                    // Modifier le contenu
                    $(".code-content > .codeContent_wrapper").html(textonly);
                } else if (this.getAttribute("class").includes('language-css')) {
                    css_count++;
                    $(this).attr("data-num_css", css_count);
                    var codeContent = $(this).text();
                    let this_data_name = $(this).attr("id");
                    let this_projet = $(this).attr("data-projet");
                    let dataname = (this_data_name != undefined) ? this_data_name : $(this).attr("data-filename");
                    
                    $('style[css_count="' + css_count + '"]').remove();
                    $('style[css_count="' + css_count + '_' + dataname + '"]').remove();
                    $('<style css_count="' + css_count + '_' + dataname + '" data-js="apply">div.codeContent_wrapper[data-projet="' + this_projet + '"] { ' + codeContent + ' }</style>').appendTo('head');
                }
                
                // Annuler le timeout précédent si existant
                if (prismTimeout) {
                    clearTimeout(prismTimeout);
                    console.log("Prism execution cancelled (debounced)");
                }
                
                // Sauvegarder le contexte
                var self = this;
                var savedCaretPos = caretPos;
                
                // Planifier l'exécution de Prism après 100ms d'inactivité
                prismTimeout = setTimeout(function() {
                    // Vérifier si Prism n'est pas déjà en cours
                    if (isPrismRunning) {
                        console.log("Prism is already running, skipping");
                        return;
                    }
                    
                    isPrismRunning = true;
                    console.log("Executing Prism.highlightAll()");
                    
                    Prism.highlightAll();
                    
                    // Restaurer la position après Prism
                    setTimeout(function() {
                        // Parcourir les nœuds texte pour trouver la position
                        var charIndex = 0;
                        var foundNode = null;
                        var foundOffset = 0;
                        
                        function findCaretPosition(node) {
                            if (node.nodeType === 3) { // Text node
                                var nextCharIndex = charIndex + node.length;
                                if (savedCaretPos >= charIndex && savedCaretPos <= nextCharIndex) {
                                    foundNode = node;
                                    foundOffset = savedCaretPos - charIndex;
                                    return true;
                                }
                                charIndex = nextCharIndex;
                            } else {
                                for (var i = 0; i < node.childNodes.length; i++) {
                                    if (findCaretPosition(node.childNodes[i])) {
                                        return true;
                                    }
                                }
                            }
                            return false;
                        }
                        
                        findCaretPosition(self);
                        
                        if (foundNode) {
                            var newRange = document.createRange();
                            var newSel = window.getSelection();
                            
                            newRange.setStart(foundNode, foundOffset);
                            newRange.collapse(true);
                            
                            newSel.removeAllRanges();
                            newSel.addRange(newRange);
                            
                            console.log("Caret restored to:", foundNode, foundOffset);
                        } else {
                            console.warn("Could not restore caret position");
                        }
                        
                        // Marquer Prism comme terminé
                        isPrismRunning = false;
                        console.log("Prism execution completed");
                    }, 10);
                }, 1000); // Délai de 100ms avant d'exécuter Prism

            // } else {
                // console.warn("Aucun textarea associé trouvé pour :", filename);
            // }
        // } /// data-origin
    };
}

        
    }
 




    //// TODO au lieu de fetch async ... utiliser jsondata directement
    async getAnswers(uniqueId) {
        /// node index_api.js --> port 4000 -> NGINX bb_test_qestionfu
        const url = this.props.state.config.getAnswers.url;
    
        const headers = Object.assign(
            {'Content-Type': 'application/json', 
                'X-Unique-ID': uniqueId
                },
            this.props.state.config.getAnswers.headers
        );
    
        console.log('URL:', url);
        console.log('Headers:', headers);
    
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: headers,
            });
    
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
    
            const data = await response.json();
            // console.log('---- Données reçues (async getAnswers) :', data);
            
                setTimeout(async () => {
                const container = document.getElementById('answersDataContainer');
                container.classList.add("getawnsers_please");

                if (container) {
                    let currentpath_fix = (data[0].currentPath!="/") ? data[0].currentPath.replace("/",""): data[0].currentPath;
                    let htmlContent = `
                    <div class="answers-container is_awnsers_show_me_help">
                        <h1 id="awnsers_questionnaire_name"><a href="`+data[0].currentPath+`">`+currentpath_fix+`</a></h1>
                        <div id="my_id">Identifiant pour retrouver les questions-réponses données :<br>
                             <input value="`+uniqueId+`"><br>
                             <a id="my_directlink" target="_top" href="`+data[0].currentPath+`?id=`+uniqueId+`#answers-container">Lien permanent (raccourcis)</a>
                        </div>
                        <div id="solu_wrap">
                            <input id="solutions" type="checkbox" name="solutions" />
                            <label for="solutions">solutions</label>
                            <input id="sans_fichiers" type="checkbox" name="sans_fichiers" />
                            <label for="sans_fichiers">sans_fichiers</label>
                        </div>
                        `;
                    

                    // console.log("--- datapls : "+data[0].result)
                    if (Array.isArray(data) && data.length > 0) {
                        const firstItem = data[0];
                        
                        if (firstItem && firstItem.answers && Array.isArray(firstItem.answers)) {
                            
                            // ✅ Utiliser une boucle for...of pour traiter dans l'ordre
                            for (let index = 0; index < firstItem.answers.length; index++) {
                                
                                const item = firstItem.answers[index];
                                htmlContent += `<div data-answer="${index + 1}"><h3 class="reponse_donne_titre" style="color:${this.props.state.config.styles.secondaryFontColor}">`
                                htmlContent += `<a href="?id=${uniqueId}&question=${index}">Question ${index}</a></h3>`;
                                
                                // console.log("---- id , "+item["id"])

                                // ✅ Traiter chaque clé dans l'ordre
                                for (const key in item) {
                                    if (item.hasOwnProperty(key)) {
                                        let value = item[key];
                                        let projet_id = item["id"];

                                        // alert(projet_id)
                                        
                                        // Si c'est un tableau (code)
                                        if (Array.isArray(value)) {
                                            // ✅ Traiter chaque fichier dans l'ordre
                                            for (let codeIndex = 0; codeIndex < value.length; codeIndex++) {
                                                const codeItem = value[codeIndex];
                                                
                                                if (codeItem && codeItem.file) {
                                                    
                                                    try {
                                                        // alert("fetch getawnsers")
                                                        // console.error("FETCH answer -- currentPath : "+firstItem.currentPath)
                                                        // console.error("FETCH answer -- file : "+codeItem.file)
                                                        const codeItem_file_fullpath = (codeItem.modified) ? codeItem.file : firstItem.currentPath + "/" + codeItem.file
                                                        const codeItem_file_modified = firstItem.currentPath + "/" + codeItem.modified;
                                                        const modified_notice = (codeItem.modified) ? "( <a target='_blank' href='/codes"+codeItem_file_modified+"' class='code_files_original'>original</a> )" : "";
                                                        const file_links = (key=="code") ? "<div class='files_links'><a target='_blank' href='/codes"+codeItem_file_fullpath+"' class='code_files'>/codes"+codeItem.file+"</a> "+modified_notice+"</div>" : "";
                                                        // console.warn("firstItem.modified === "+codeItem.modified)
                                                        // console.warn("codeItem_file_fullpath == "+  codeItem_file_fullpath)
                                                        
                                                        const content = await this.fetch_file_content(codeItem_file_fullpath);
                                                        const codeItemAtIndex = item[key][codeIndex];
                                                        // console.log("Debug - codeItemAtIndex:", codeItemAtIndex);

                                                        const is_type = codeItemAtIndex?.type || "markup"; // Default to "markup" if undefined
                                                        const is_para_original = codeItemAtIndex?.para;
                                                        // console.log("Debug - is_para_original:", is_para_original);
                                                        const is_para = is_para_original ? 
                                                            is_para_original.replace(/nohelp/g, "getawnsers") 
                                                            : "no_para_getawnsers";

                                                        // console.log("Debug - is_para (final):", is_para);
                                                                
                                                        const sub_folder = firstItem.currentPath;
                                                        const content_fix = (is_type=="markup") 
                                                            ? content
                                                                .replace(/&/g, "&amp;")
                                                                .replace(/</g, "&lt;")
                                                                .replace(/>/g, "&gt;")
                                                                .replace(/"/g, "&quot;")
                                                                .replace(/'/g, "&#039;")
                                                                .replace(/\/\{sub_folder\}/g, sub_folder)
                                                            : content.replace(/\/\{sub_folder\}/g, sub_folder);
                                                        

                                                        // console.log(is_type)
                                                        if ((is_type == "image") || (key=="order") || (key=="para")) {
                                                            // htmlContent += `lol`


                                                        } else if (is_type === "render") {
                                                            htmlContent += `<p data-key="render">${content_fix}</p>`
                                                            // alert(content)
                                                        // } else if (is_type === "css") {
                                                            // htmlContent += `<p data-key="${key}"><strong>${key} ${codeIndex + 1}:</strong>${file_links} <pre data-type=${is_type} data-key=${codeIndex}><code class='line-numbers show-language ${is_para} language-${is_type}' data-projet='${projet_id}' data-filename='${codeItem.file}'>${content_fix}</code></pre></p>`;
                                                        } else {
                                                            htmlContent += `<div><p data-key="${key}"><strong>${key} ${codeIndex + 1}:</strong></p>${file_links} <pre data-type=${is_type} data-key=${codeIndex} class="getawnsers_mod"><code class='getawnsers_mod line-numbers show-language ${is_para} language-${is_type}' data-projet='${projet_id}' data-filename='${codeItem.file}'>${content_fix}</code></pre></div>`;
                                                        }
                                                        // htmlContent += `<p data-key="${key}_${codeIndex + 1}"><strong>${key} ${codeIndex + 1}:</strong><pre data-type=${is_type} data-key=${codeIndex}><code class='line-numbers show-language ${is_para} language-${is_type}'>${content_fix}</code></pre></p>`;

                                                    } catch (error) {

                                                        console.error("!!!! Erreur :", error);
                                                        htmlContent += `<p data-key="${key}"><strong>${key}:</strong> Erreur de chargement</p>`;

                                                    }
                                                }
                                            }
                                        } 



                                        
                                        // Si c'est un objet (mais pas un tableau)
                                        else if (typeof value === 'object' && value !== null) {
                                            if (key == "code" && value.file) {
                                                try {
                                                    const content = await this.fetch_file_content(value.file);
                                                    htmlContent += `<p data-key="${key}"><strong>${key}:</strong></p><pre>${content}</pre>`;
                                                } catch (error) {
                                                    console.error("Erreur :", error);
                                                    htmlContent += `<p data-key="${key}"><strong>${key}:</strong> Erreur de chargement</p>`;
                                                }
                                            }
                                        } 




                                        // Sinon, valeur simple
                                        else if (key!="id" && value.length!=0) {
                                            let key_fix=key.replace("answer","Réponse donnée").replace("additionalInput","Remarques (optionnelles)").replace("explo","Précisions")
                                            htmlContent += `<p data-key="${key}"><strong>${key_fix}:</strong></p><div class="reponse_donnee ${key}">${value}</div>`;
                                        }




                                    }
                                }




                                //// GETRESUTS
                                let test_id= item['id']
                                let sub_folder=data[0].currentPath;
                                console.log("--- GETRESUTS ---- "+test_id)
                                // console.error(data[0].currentPath)

                                let result_file = `${sub_folder}/${test_id}.result`

                                console.warn("----- result_file == \n"+result_file+"-----\n\n")
                                // const resultContent = await this.fetch_file_content(result_file);
                                // console.log("-------- \n" + resultContent + "\n---------------END")
                                htmlContent += `<div class="results_wrapper answer"><strong class="answer label">Solution suggéréé :</strong><br>` + await this.fetch_file_content(result_file) + `</div>`
                                


                    


                                htmlContent += '</div>';
                            }
                        } else {
                            htmlContent += `<p>Answers n'est pas défini</p>`;
                        }
                    } else {
                        htmlContent += `<p>Données non valides : ${JSON.stringify(data)}</p>`;
                    }
                    
                    htmlContent += '</div>';
                    container.innerHTML = htmlContent;

                    this.applyPrismHighlighting();
                    this.applyScriptsnormcss();
                    // alert("go")

                    this.force_applyScripts();

                }
            }, 800);
            
        } catch (error) {
            console.error('Erreur lors de la récupération des réponses:', error);
        }
    }

    onChange(event) {
        this.setState({
            value: event.target.value
        })

        this.props.api.updateState({
            question: Object.assign(this.props.state.question, {answer: event.target.value})
        });

    }

    
    onSubmit(event) {
        event.preventDefault();

        // if (!this.props.state.question.answer) {
        //     return;
        // }

        // Défilement vers le haut de la page
        window.scrollTo(0, 0);

        // // Générer un identifiant unique
        // const uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);
        const uniqueId = this.state.uniqueId;
        const uniqueId_state = uniqueId;
        

        // Ajouter le champ supplémentaire à la question actuelle
        const updatedQuestion = Object.assign(this.props.state.question, { additionalInput: this.state.additionalInput });

        // Store current answer to the collection of answers.
        const answers = [...this.props.state.answers, updatedQuestion];


        $('.changed_code_element').each(function() {
            // alert("changed_code_element")
            // let datafilename = $(this).attr("data-filename")
            let datafilename = $(this).find("code").attr("data-filename")
            let datatype = $(this).attr("data-type")
            const currentPath = window.location.pathname;
            const sub_folder = currentPath === "/" ? "" : currentPath;
            const file_path = "/codes"+sub_folder+"/"

            //// SAVE TO FILE
            getCodeContent_thenSave(file_path, datafilename, uniqueId_state, "changed_code_element", datatype)
            // alert("\n -- currentPath == "+currentPath +"\n -- sub_folder == "+sub_folder +"\n -- file_path == "+file_path +"\n -- uniqueId_state == "+uniqueId_state)


            // file_path, datafilename, uniqueId_state
            const filepath_fix = currentPath+ "/data/"+ uniqueId_state+ "_"+ datafilename;
            // Parcourir et remplacer
            answers.forEach((item) => {
              if (item.code && Array.isArray(item.code)) {
                item.code.forEach((codeItem) => {
                  if (codeItem.file === datafilename) {
                    codeItem.file = filepath_fix;
                    codeItem.modified = datafilename;
                  }
                });
              }
            });
            

            console.error("--------------- MOD")
            // Afficher le résultat
            console.log(JSON.stringify(answers, null, 2));
            console.error("--------------- MOD END")

            
        }); /// changed_code_element

        // Ajouter l'identifiant unique aux données
        const dataToSubmit = {
            timestamp: new Date().toISOString(),
            uniqueId: uniqueId,
            currentPath: window.location.pathname,
            answers: answers
        }

        this.props.api.updateState({
            answers
        });

        const currentQuestionIndex = this.props.state.currentQuestionIndex + 1;
        const question = this.props.state.config.questions[currentQuestionIndex];

        if (!question) {
            this.props.api.showMessage('Bravo, toutes les réponses sont données.');


            // Send the form information into the provided endpoint.
            if (this.props.state.config.submission.url) {
                this.submitAnswers(dataToSubmit);
            }

            // Ajouter un délai de 2 secondes avant d'appeler getAnswers
            setTimeout(() => {
                this.getAnswers(uniqueId);
                /// REDIRECT
                // window.location.search =  'id='+uniqueId;
                let redirpls;
                if (confirm("TEST fini, lien permanent (à garder) =\n"+window.location + "?id=" + uniqueId +"\n\nRedirection ?") == true) {
                    window.location.search =  'id='+uniqueId;
                } else {
                redirpls = "You canceled!";
                }
                // confirm("TEST fini, lien permanent (à garder) =\n"+window.location + "?id=" + uniqueId)

            }, 500); // Délai de 2000 millisecondes (2 secondes)


        }

        this.props.api.updateState({
            currentQuestionIndex,
            question
        });

        this.setState({
            value: '',
            additionalInput: ''
        });
    }




    
    submitAnswers(answers) {
        /// node index_api.js --> port 4000 -> NGINX bb_test_qestionfu
        fetch(this.props.state.config.submission.url, {
            method: 'POST',
            headers: Object.assign({'Content-Type': 'application/json'}, this.props.state.config.submission.headers),
            body: JSON.stringify(answers)
        })
        .then(response => {
            console.info('Submit form data has succeeded.', response);
        })
        .catch(error => {
            this.props.api.showMessage('Error! Le serveur API ne répond pas.');
            console.error('Submit form data has failed.', error);
        });
    }

    
    render() {

        if (!this.props.state.question) {
            return null;
        }

        const inputStyle = {
            color: this.props.state.config.styles.primaryFontColor,
            borderColor: this.props.state.config.styles.primaryFontColor
        };

        const buttonStyle = {
            color: this.props.state.config.styles.primaryFontColor,
            borderColor: this.props.state.config.styles.primaryFontColor
        };

        const buttonLabel = this.props.state.currentQuestionIndex === (this.props.state.config.questions.length - 1) ? 'Envoyer' : 'Continuer';


        const style = {
            color: this.props.state.config.styles.secondaryFontColor
        };

        

        const searchParams = new URLSearchParams(window.location.search);
        const idParam = searchParams.get('id');        
        const questionParam = searchParams.get('question');
        const questparamtest = ((questionParam==0) || (questionParam==null)) ? false : true;
        console.log("questparamtest === "+questparamtest)
        let hide_questionnaire_id = (idParam) ? "have_id" : "no_id";
        let hide_questionnaire = (questionParam) ? hide_questionnaire_id+ " questionparam" : hide_questionnaire_id;
        this.props.state.currentQuestionIndex
        
        const initialPlaceholder = "( voire développement : \nquels doutes puis hypothèses motivant la réponse... \nhésitation, donner plusieurs réponses )";
        let placeholder_response = this.props.state.currentQuestionIndex > 0 ? "" : initialPlaceholder;

        // Prism.highlightAll();

            
        
        const getresults = async (questionId) => {
            console.log("ID de la question :", questionId);
        
            let test_id = questionId;
            let sub_folder = window.location.pathname;
        
            console.log("--- GETRESULTS ---- " + test_id);
            let result_file = `/codes${sub_folder}/${test_id}.result`;
            console.warn("----- result_file == \nhttps://test.bonnebulle.xyz" + result_file + "\n-----\n\n");
        
            try {
                const response = await fetch(result_file);
                console.log("\n\n\n\n------------------- response (getresults)", response);
        
                if (!response.ok) throw new Error('Network response was not ok');
        
                const contentType = response.headers.get('content-type');
                console.log("Content-Type:", contentType);
        
                if (contentType && contentType.includes('text/html')) {
                    console.warn("Le fichier retourné est au format HTML, pas le format attendu.");
                    document.getElementById('result_wrap').innerHTML = "Erreur : Contenu HTML inattendu.";
                    return '';
                }
        
                const text = await response.text();
                console.log("\n\n\n\n------------------- text");
                console.log(text);
        
                // Injecter le texte dans #result_wrap
                const resultElement = document.getElementById('result_wrap');
                if (resultElement) {
                    // selon le format attendu, vous pouvez utiliser innerText ou innerHTML
                    resultElement.innerText = "<a href='https://test.bonnebulle.xyz" + result_file + "'>Result_file</a>"+text; 
                } else {
                    console.warn("Élément #result_wrap non trouvé dans le DOM");
                }
        
                console.warn("fetch_file_content END");
                return text;
        
            } catch (error) {
                console.error(`Erreur lors du chargement du fichier ${result_file}:`, error);
                console.warn("ERROR fetch_file_content END");
                const resultElement = document.getElementById('result_wrap');
                if (resultElement) {
                    resultElement.innerHTML = "Erreur lors du chargement du fichier.";
                }
                return '';
            }
        };


        const uniqueId_state = this.state.uniqueId;
        // alert(uniqueId_state)
        const sub_folder= window.location.pathname;
        const hostname=window.location.hostname


        const file_path_results = `${sub_folder}/${this.props.state.question.id}.result`
        const file_results = `${this.props.state.question.id}.result`


        return (
            <div className="QuestionBox">



                {/* Bouton pour afficher/masquer la TOC */}
                <button
                    className="toc-toggle-button"
                    onClick={this.toggleTOC}
                >
                    {this.state.showTOC ? 'Masquer' : 'TOC'}
                </button>

                {/* Afficher la TOC si showTOC est vrai */}
                {this.state.showTOC && this.renderTOC()}
                        
                <div id="toggle_view_wrapper">
                    <label htmlFor="toggle_view">Vue large</label>
                    <input id="toggle_view" type="checkbox"  name="toggle_view" />
                </div>

                {(!idParam || questionParam) && (
                    <form className={hide_questionnaire} onSubmit={this.onSubmit.bind(this)} name="quetionform">


                    <h1 id='question_title'>{this.props.state.question.title}</h1>
                    <h2 id='question_id' className='idname'>{this.props.state.question.id}</h2>

                    {this.props.state.question.explo && <p id="question_description">{this.props.state.question.explo}</p>}
                    {this.props.state.question.code.map((codeItem, index) => {



                        // console.log("RENDER ---- "+codeItem.file)
                        // console.log(content)

                        /// Params
                        const currentPath = window.location.pathname;
                        const sub_folder = currentPath === "/" ? "" : currentPath;
                        
                        // LOAD
                        // Replace "{sub_folder}" in files -> current folder_projet
                        // console.log("codeItem codeItem codeItem")
                        // console.log(codeItem)

                        const content = (this.state.loadedHtml[codeItem.file] || '').replace(/\/\{sub_folder\}/g, sub_folder);

                        // img
                        let file_path = `/codes${sub_folder}/`
                        let file_pls = `${file_path}${codeItem.file}`;
                        let file_plsnocode = `/codes${sub_folder}/${codeItem.file}`;


                        // const my_class = (codeItem.type === "css") ? "prewrap not_sticky" : "prewrap force_sticky";
                        const my_class = "prewrap not_sticky";
                        const is_editable = ( codeItem.para.includes("lock") ) ? "false" : "true";

                        const nameWithoutExtension = codeItem.file.replace(/\.[^.]+$/, ""); // Supprime la dernière extension
                        switch (true) {
                            case codeItem.para.includes("large") && codeItem.type.includes("markup"):
                                codeItem.para = codeItem.para.replace("large","large force_sticky");
                            break;
                            default:
                                codeItem.para = codeItem.para;
                        }

                        const topbuttons = (
                            <div className="file_buttons">
                                <div
                                    className="locker_file files_buttons">
                                    <i className="material-icons lock"></i>
                                </div>
                                
                                <div
                                    className="stiky_or_not files_buttons"
                                    onClick={e => e.target.closest('.prewrap') && (e.target.closest('.prewrap').classList.toggle('not_sticky'), e.target.closest('.prewrap').classList.toggle('force_sticky'))}
                                >
                                    {/* <img src="/img/pinboard.svg" /> */}
                                    <i className="material-icons push_pin"></i>
                                </div>


                                <div
                                    className="fullscreen_button files_buttons"
                                    onClick={() => {
                                        const prewrap = document.querySelector(`.prewrap[data-filename="${codeItem.file}"]`);
                                        if (prewrap) {
                                            // prewrap.classList.toggle("fullscreen-mode");
                                            clonecode()
                                        }
                                    }}
                                >
                                    Plein écran
                                </div>


                                <div className="dwl_file files_buttons">
                                    
                                    <div className='file_name'>{codeItem.file}</div>
                                    <a title="Fichier original" className='save_file original' href={file_pls} target="_blank" rel="noopener noreferrer">
                                        original
                                    </a>
                                </div>

                                <div
                                    className="save_file save_file_tofile files_buttons"
                                    onClick={() => getCodeContent_thenSave(file_path, codeItem.file, uniqueId_state, "satofile")}
                                >
                                    télécharger
                                </div>
                                <div
                                    className="save_file save_file_toserver files_buttons"
                                    onClick={() => getCodeContent_thenSave(file_path, codeItem.file, uniqueId_state, "direct")}
                                >
                                    <span className='auto_save_txt'></span><span className='save_txt'>sauvegarder</span>
                                </div>
                                <div
                                    className="save_file load_files files_buttons"
                                    onClick={(e) => this.handleLoadFilePrompt(e)}
                                >
                                    charger
                                </div>
                            </div>
                        );


                        const toptextarea = (
                            <textarea
                                key={`textarea_${index}`}
                                id="editing"
                                data-filename={codeItem.file}
                                value={this.state.textareaValues[codeItem.file] !== undefined ? this.state.textareaValues[codeItem.file] : content}
                                onLoad={this.updateTextareaHeight.bind(this, codeItem.file)}
                                onChange={(e) => {
                                    const newValue = e.target.value;
                                    const fileName = codeItem.file;

                                    // Mettre à jour textareaValues dans l'état
                                    this.setState(prevState => ({
                                        textareaValues: {
                                            ...prevState.textareaValues,
                                            [fileName]: newValue
                                        }
                                    }));

                                    // Appeler updateCodeContent pour synchroniser le code
                                    this.updateCodeContent(fileName, newValue, codeItem.type);
                                }}
                            />
                        )

                        ///// CASES
                        if (codeItem.type === "image") {
                            return !this.state.imageError ? (
                                <img
                                    key={index}
                                    src={file_pls}
                                    onError={() => this.setState({ imageError: true })}
                                    alt="Image non disponible"
                                />
                            ) : (
                                <p key={index}>Image non disponible -- {file_pls}</p>
                            );

                        } else if (codeItem.type === "render") {

                            return (
                                <div key={index} className={`prewrap ${codeItem.para} ${codeItem.type}`} data-filename={`${codeItem.file}`}>
                                    {/* <pre> */}
                                        <div
                                            data-filename={`${codeItem.file}`}
                                            dangerouslySetInnerHTML={{ __html: content }}
                                        />
                                        
                                    {/* </pre> */}
                                </div>
                            ); 

                        } else if (codeItem.type === "txt") {
                            
                            return (
                                <div key={index} className={`prewrap ${codeItem.para} ${codeItem.type}`} data-filename={`${codeItem.file}`}>
                                    {file_plsnocode}
                                    {this.state.txtContents[file_plsnocode] || 'Chargement...'}

                                </div>
                            );
                        
                        } else if ((codeItem.type === "css") || (codeItem.type === "markup")) {

                            return (
                                <div key={index} className={`${my_class} ${codeItem.para} ${codeItem.type}`} data-filename={`${codeItem.file}`}>
                                    {topbuttons}
                                    {toptextarea}
                                    <pre data-type={`${codeItem.para} language-${codeItem.type}`}>
                                        <code
                                            className={`line-numbers show-language ${codeItem.para} language-${codeItem.type}`}
                                            data-filename={`${codeItem.file}`}
                                            data-projet={`${this.props.state.question.id}`}
                                            contentEditable={`${is_editable}`}
                                            spellCheck="false"
                                            data-id={`${codeItem.id}_${codeItem.type}`}
                                        >
                                            {content}
                                        </code>
                                    </pre>
                                </div>

                            ); // Return else (default)

                        
                        } else { // autre, default :

                            return (

                                <div key={index} className={`${my_class} ${codeItem.para} ${codeItem.type}`} data-filename={`${codeItem.file}`}>
                                    {topbuttons}
                                    {toptextarea}
                                    <pre>
                                        <code
                                            className={`line-numbers show-language ${codeItem.para} language-${codeItem.type}`}
                                            data-filename={`${codeItem.file}`}
                                            data-projet={`${this.props.state.question.id}`}
                                            contentEditable="false" // PREVENT
                                            spellCheck="false"
                                        >
                                            {content}
                                        </code>
                                    </pre>
                                </div>

                            ); // Return else (default)

                        }
                        ///// END CASES

                    })} 
                    {/* this.props.state.question.code.map((codeItem, index) */}
                    {/* {this.props.state.question.code.map((codeItem, index) => { */}


                    {questparamtest==false && (
                        
                
                        <div id="botom_form" className='resp_background'>


                            
                            <label className="input-sizer stacked">
                            <span>Réponse: </span>
                            <textarea
                                id="letsgo"
                                onChange={this.onChange.bind(this)}
                                onKeyDown={(e) => {
                                    if (e.ctrlKey && e.key === 'Enter') {
                                        e.preventDefault(); // Empêche le comportement par défaut (saut de ligne)
                                        this.onSubmit({ preventDefault: () => {} }); // Déclenche la soumission
                                    }
                                }}
                                    
                                placeholder={placeholder_response}
                                value={this.state.value}
                                style={inputStyle}
                            ></textarea>
                            </label>
                            <input
                                id="input_remarques"
                                type="text"
                                placeholder="Remarques (optionnelles)"
                                value={this.state.additionalInput}
                                onChange={this.handleAdditionalInputChange}
                                style={inputStyle}
                            />
                            <button id="letsub" type="submit" style={buttonStyle}>{buttonLabel}</button>
                        </div>
                    )} 
                    {/* /// questparamtest */}
                    
                    {questparamtest && (
                        <div  id="questpls"><h1>Répondre aux questions dans l'ordre (déso)</h1>( <a id="backquestion" href={`https://${hostname}${sub_folder}?question=0`}>Question 0</a> )</div>
                    )}

                    

                    </form>
                )} {/* idParam */}
                {/* {!idParam || questionParam && ( */}


                {/* {this.props.state.question.result} */}

                <span className="resp_background wrap">
                    {/* Afficher la question précédente si elle existe */}
                    {this.props.state.currentQuestionIndex > 0 && (
                        <p className="previous-question-title nextprev resp_background">
                            <span className="title_nextprev" style={style}>Question précédente :</span><br /> {this.props.state.currentQuestionIndex - 1}.
                            <a href={`?question=${this.props.state.currentQuestionIndex - 1}${idParam ? `&id=${idParam}` : ''}`}>{this.props.state.config.questions[this.props.state.currentQuestionIndex - 1].title}</a>
                            <br />
                            <span className='shortnape'>{this.props.state.config.questions[this.props.state.currentQuestionIndex - 1].short}</span>
                        </p>
                    )}
                    {this.props.state.config.questions[this.props.state.currentQuestionIndex + 1] && (
                        <p className="next-question-title nextprev resp_background">
                            <span className="title_nextprev" style={style}>Question suivante :</span><br /> {this.props.state.currentQuestionIndex + 1}.
                            <a href={`?question=${this.props.state.currentQuestionIndex + 1}${idParam ? `&id=${idParam}` : ''}`}>{this.props.state.config.questions[this.props.state.currentQuestionIndex + 1].title}</a>
                            <br />
                            <span className='shortnape'>{this.props.state.config.questions[this.props.state.currentQuestionIndex + 1].short}</span>
                        </p>
                    )}
                
                <div 
                    // onClick={() => getCodeContent_thenSave(`/codes${file_path_results}`, file_results, uniqueId_state, "satofile")}
                >
                                     <a id="resultats_file_link" href={`/codes${sub_folder}/${this.props.state.question.id}.result`}>Solutions / indices / explication</a>

                </div>



                {(!idParam || questionParam) && (
                    <div id="bottomToc">

                    <button
                        className="toc-toggle-button resp_background"
                        onClick={this.toggleTOC}
                    >
                        {this.state.showTOC ? 'Masquer' : 'TOC'}
                    </button>
                    </div>
                )}

                {this.state.showTOC && this.renderTOC()}
                        

                    {/* Section pour déclencher getAnswers avec un ID personnalisé, uniquement pour la première question */}
                    {this.props.state.currentQuestionIndex === 0 && (
                    <div id='unique-id-wrapper' className='resp_background'>
                        {(() => {
                            /// SI ?id afficher "/" home ici 
                            // const searchParams = new URLSearchParams(window.location.search);
                            // const idParam = searchParams.get('id');
                            // return idParam ? (
                            //     <a href="/" id="home">
                            //         <img className='icon small' src='questionful.png' /> /
                            //     </a>
                            // ) : null;
                        })()}

                        <div className="unique-id-section resp_background">
                            <h3 className="unique-id-title">Récupérer vos réponses avec votre ID unique</h3>
                            <strong>( généré lors de la dernière question-réponse )<br />( penser à le noter / sauvegarder )</strong>
                            <form onSubmit={this.handleUniqueIdSubmit}>
                                <input
                                    id="uniqueidinput"
                                    type="text"
                                    placeholder="Entrez un ID unique"
                                    value={this.state.uniqueIdInput}
                                    onChange={this.handleUniqueIdChange}
                                    style={inputStyle}
                                />
                                <button type="submit" style={buttonStyle}>Récupérer les réponses</button>
                            </form>
                        </div> 
                    </div>
                    
                    )}
                </span>
            
            </div> //// QuestionBox
        )   ////// END RETURN

    }

}

export default QuestionBox;