let isFirstSaveCall = true;
var currentTab = 0; // Current tab is set to be the first tab (0)
var formTitleJson = {};
var formTitleEtape = {};
var formEtapeQuestions = {};
var formEtapeQuestionsType = {};
var register = "false";
var recapLabel = [];
var recapUnite = [];
var recapId = [];
var recapResAdd = [];
var resPayment = [];
var nomVariable = [];
var encaissement = "";

function scrollWithOffset() {
  const el = document.getElementById('flexibleFormWrapper');
  if (!el) {
    console.warn('Element not found: #flexibleFormWrapper');
    return;
  }

  const offsetFromTop = window.innerHeight * 0.20; // 30%
  const elPageY = el.getBoundingClientRect().top + window.pageYOffset;
  const scrollToY = elPageY - offsetFromTop;

  window.scrollTo({
    top: scrollToY,
    behavior: 'auto'
  });
}

function runSnippet(snippet) {
  if (!snippet || typeof snippet !== 'string') {
    return Promise.resolve();
  }

  // Strip backend “null ” prefix or excess whitespace
  snippet = snippet.trim().replace(/^null\s*/i, '');

  return new Promise((resolve, reject) => {

    /* ---------------------------------------------------
     *  Helper → wrap arbitrary code in try/catch so that
     *           runtime errors bubble up to our Promise.
     * --------------------------------------------------- */
    const wrapCode = code => `(function(){try{${code}}catch(e){throw e;}})();`;

    /* ------------- CASE 1 – snippet contains <script> ---- */
    if (snippet.includes('<script')) {
      const wrapper = document.createElement('div');
      wrapper.innerHTML = snippet;

      const scripts = Array.from(wrapper.querySelectorAll('script'));
      let chain = Promise.resolve();

      scripts.forEach(node => {
        chain = chain.then(() => new Promise((res, rej) => {
          const s = document.createElement('script');

          /* EXTERNAL <script src="…"> ---------------------- */
          if (node.src) {
            s.src = node.src;
            s.async = node.async || false;

            /* ▶ network / load errors */
            s.onerror = () => rej(new Error(`Impossible de charger ${node.src}`));

            /* For external files `onload` fires even if they throw
               runtime errors, so we temporarily listen to window.onerror */
            const handleRuntime = (msg, url, line, col, err) => {
              window.removeEventListener('error', handleRuntime);
              rej(err || new Error(msg));
              return true;   // prevent default console error
            };
            window.addEventListener('error', handleRuntime, { once: true });

            s.onload = () => {
              window.removeEventListener('error', handleRuntime);
              res();
            };
          }

          /* INLINE <script> -------------------------------- */
          else {
            /* wrap code so thrown error reaches us */
            s.textContent = wrapCode(node.textContent);

            const handleRuntime = (msg, url, line, col, err) => {
              window.removeEventListener('error', handleRuntime);
              rej(err || new Error(msg));
              return true;
            };
            window.addEventListener('error', handleRuntime, { once: true });

            /* Because inline scripts execute immediately after insertion,
               we can resolve in the next macrotask */
            setTimeout(res, 0);
          }

          document.head.appendChild(s);
        }));
      });

      chain.then(resolve).catch(reject);
      return;      // do NOT fall through to “plain JS” section
    }

    /* ------------- CASE 2 – plain JS string --------------- */
    try {
      /* wrap so `throw` triggers our catch below */
      (new Function(wrapCode(snippet)))();
      resolve();
    } catch (err) {
      reject(err);
    }
  });
}


function pondUploadsStillRunning() {
  // console.log('pondUploadsStillRunning');
  // ①  Grab the DOM node for the visible tab
  const tab = document.querySelector('.tab[style*="display: block"]');
  if (!tab) return false;          // safety

  // ②  Inspect every FilePond inside that tab
  return [...tab.querySelectorAll('.filepond--root')].some(root => {
    const pond = FilePond.find(root);
    if (!pond) return false;

    return pond.getFiles().some(f => [
      FilePond.FileStatus.PROCESSING_QUEUED,
      FilePond.FileStatus.PROCESSING,
      FilePond.FileStatus.PROCESSING_ERROR,
      FilePond.FileStatus.PROCESSING_REVERT_ERROR
    ].includes(f.status));
  });
}

function refreshNavButtons() {
  // console.log('refreshNavButtons');
  const $nextBtn = $('#nextBtn');
  const $prevBtn = $('#prevBtn');
  const $saveBtn = $('#saveBtn');

  const busy = pondUploadsStillRunning();

  // Disable all navigation buttons during upload
  $nextBtn.prop('disabled', busy).toggleClass('disabled', busy);
  $prevBtn.prop('disabled', busy).toggleClass('disabled', busy);
  $saveBtn.prop('disabled', busy).toggleClass('disabled', busy);

  // Add visual feedback class
  if (busy) {
    $nextBtn.addClass('upload-disabled').attr('title', 'Téléchargement en cours...');
    $prevBtn.addClass('upload-disabled').attr('title', 'Téléchargement en cours...');
    $saveBtn.addClass('upload-disabled').attr('title', 'Téléchargement en cours...');
  } else {
    $nextBtn.removeClass('upload-disabled').removeAttr('title');
    $prevBtn.removeClass('upload-disabled').removeAttr('title');
    $saveBtn.removeClass('upload-disabled').removeAttr('title');
  }
}

function showTab(n, prev) {
  // This function will display the specified tab of the form...
  tab = document.getElementsByClassName("tab");
  yinput = tab[n].getElementsByTagName("input");

  var spansecure = document.getElementsByClassName("spansecureetape");

  if (prev != "prev") {
    Array.prototype.forEach.call(spansecure, function (el, index) {
      if (index == n) {
        spanmsecure = el;

        secureemail = false;
        securesms = false;

        for (i = 0; i < yinput.length; i++) {
          if (yinput[i].name == "text-contact_email_secure") {
            secureemail = true;
          } else if (yinput[i].name == "text-contact_tel_secure") {
            securesms = true;
          }
        }

        if (
          (spanmsecure.innerText != null && spanmsecure.innerText != "") ||
          secureemail ||
          securesms
        ) {
          $("div.inpdiv")
            .not(
              "[name=div-contact_email_secure], [name=div-contact_tel_secure], [style*='display: block']"
            )
            .prop("hidden", true);
          $("div.validCodeverify").prop("hidden", true);

          if (spanmsecure.innerText == "Email") {
            if ($("div.validCodeverifyemail").length > 0) {
              $("div.validCodeverifyemail")
                .find("#text-contact_email_secure")
                .each(function () {
                  $(this).removeAttr("required");
                });

              $("div.validCodeverifyemail")
                .find("#text-validate-code-email")
                .each(function () {
                  $(this).removeAttr("required");
                });

              $("div.inpdiv")
                .not(
                  "[name=div-vallidate-code-email], [name=div-contact_email_secure], [name=div-vallidate-code-sms]"
                )
                .prop("hidden", false);
            }
          } else if (spanmsecure.innerText == "SMS") {
            if ($("div.validCodeverifysms").length > 0) {
              $("div.validCodeverifyemail")
                .find("#text-contact_tel_secure")
                .each(function () {
                  $(this).removeAttr("required");
                });

              $("div.validCodeverifyemail")
                .find("#text-validate-code-sms")
                .each(function () {
                  $(this).removeAttr("required");
                });

              $("div.inpdiv")
                .not(
                  "[name=div-vallidate-code-sms], [name=div-contact_tel_secure], [name=div-vallidate-code-email]"
                )
                .prop("hidden", false);
            }
          }
        } else {
          $("div.inpdiv")
            .not(
              "[name=div-contact_email_secure], [name=div-contact_tel_secure], [name=div-vallidate-code-email], [name=div-vallidate-code-sms]"
            )
            .prop("hidden", false);
        }
      }
    });
  } else {
    $("div.validCodeverifyemail").prop("hidden", true);
    $("div.validCodeverifysms").prop("hidden", true);
  }

  var x = document.getElementsByClassName("tab");
  var mx = document.getElementsByClassName("tttab");

  x[n].style.display = "block";

  if (mx[n] != undefined) {
    mx[n].style.display = "block";
  }

  // ... and fix the Previous/Next buttons:
  if (n == 0) {
    console.log('First tab, hiding previous button');
    if (document.getElementById("prevBtn") != null) {
      document.getElementById("prevBtn").style.display = "none";
    }
  } else {
    document.getElementById("prevBtn").style.display = "inline";

    scrollWithOffset();
  }

  if (n == x.length - 1) {
    if (document.getElementById("nextBtn") != null) {
      document.getElementById("nextBtn").innerHTML = "Enregistrer";
    }
  } else {
    document.getElementById("nextBtn").innerHTML = "Suivant";
  }
  // ... and run a function that will display the correct step indicator:
  fixStepIndicator(n);
  $(".flexible-form .btn").removeClass("disabled");
  $(".flexible-form .btn-primary").removeClass("btn-loading");
  refreshNavButtons();
}

function nextPrev(btn, n, prev) {

  if (pondUploadsStillRunning()) {
    // console.log('Navigation blocked - uploads in progress');
    alert('Veuillez attendre la fin du téléchargement avant de continuer.');
    return false;
  }

  // disable button after clicking on suivant button
  $(".flexible-form .btn").addClass("disabled");
  $('.error-msg').remove();
  $(btn).addClass("btn-loading");

  if (n == -1) {
    $(".flexible-form .btn").removeClass("disabled");
    $(btn).removeClass("btn-loading");
  }

  function saveForm() {

    $.ajax({
      url: dataJsonForm.data_response,
      type: "POST",
      timeout: 60000,
      data: {
        token: $("#token").val(),
        mtoken: $("#token").val(),
        form: $("#form").val(),
        title_form: $("#title_form").val(),
        data: JSON.stringify(formTitleJson),
        sendmail: sendemail,
        sendPdf: sendPdf,
        last_step: currentTab === x.length - 1 ? 'true' : 'false',
        is_first_step: isFirstSaveCall ? 'true' : 'false',
        copie_email: ($("#formCopieEmail").val() !== "") ? $("#formCopieEmail").val() : null,
        redirect_url: ($("#formRedirectUrl").val() !== "") ? $("#formRedirectUrl").val() : null,
        script_save: ($("#formScriptSave").val() !== "") ? $("#formScriptSave").val() : null,
        script: ($("#formScript").val() !== "") ? $("#formScript").val() : null
      },
      dataType: "json",
      success: function (data) {
        isFirstSaveCall = false;

        if (data.status === "error" && data.code === "CAPTCHA_ERROR") {
          var $recaptchaInput = $("[data-type='captcha']");
          $recaptchaInput.addClass('invalid');
          insertValidationMessage($recaptchaInput, "La vérification CAPTCHA a échoué. Veuillez réessayer.");
          $("#refreshCaptchaBtn").trigger("click");
          return;
        }

        if (data.script) {
          runSnippet(data.script)
            .then(() => {
              if (data.redirect_url?.startsWith('http')) {
                window.location.href = data.redirect_url;
              }
            })
            .catch(err => {
              const msg = (
                err?.message ||
                err?.error?.message ||
                String(err)
              ).replace(/</g, '&lt;').replace(/>/g, '&gt;');

              Swal.fire({
                icon: 'error',
                title: 'Une petite erreur s’est glissée…',
                html: `
                  <p class="mb-2">Le script n’a pas pu s’exécuter correctement.</p>
                  <p class="mb-0">Détail&nbsp;:
                    <code style="white-space:pre-wrap">${msg}</code>
                  </p>
                `,
                confirmButtonText: 'Fermer',
                allowOutsideClick: false,
                customClass: { confirmButton: 'btn btn-primary' },
                buttonsStyling: false
              });
            });
        } else if (data.redirect_url && data.redirect_url.startsWith('http')) {
          window.location.href = data.redirect_url;
        }

        // 3️⃣  Run script_save (if present) – no redirect afterwards
        if (data.script_save) {
          runSnippet(data.script_save)
            .catch(err => {

              /* 1️⃣  On fabrique une chaîne sûre à afficher
                 (err peut être Error, ErrorEvent ou simple string) */
              const msg = (
                err?.message ||    // Error standard
                err?.error?.message ||    // ErrorEvent
                String(err)                        // fallback
              ).replace(/</g, '&lt;').replace(/>/g, '&gt;');   // échappe < >

              /* 2️⃣  SweetAlert 2 */
              Swal.fire({
                icon: 'error',
                title: 'Une petite erreur s’est glissée…',
                html: `
                <p class="mb-2">Le script partiel n’a pas pu s’exécuter correctement.</p>
                <p class="mb-0">
                  Détail&nbsp;: <code style="white-space:pre-wrap">${msg}</code>
                </p>
              `,
                confirmButtonText: 'Fermer',
                allowOutsideClick: false,
                customClass: { confirmButton: 'btn btn-primary' },
                buttonsStyling: false
              });
            });
        }

        $("#token").val(data.token);
        // Hide the current tab:
        x[currentTab].style.display = "none";
        // Increase or decrease the current tab by 1:
        currentTab = currentTab + n;
        // if you have reached the end of the form...
        if (currentTab >= x.length) {
          // ... the form gets submitted:
          document
            .getElementById("formResult")
            .classList.remove("d-none");
          document.getElementById("recapCard").classList.add("d-none");
          document.getElementsByClassName("flexible-form__recaptcha-info")[0].classList.add("d-none");
          $(".step.completed").addClass("done");
          if (document.getElementById("nextBtn") != null) {
            document.getElementById("nextBtn").style.display = "none";
            document.getElementById("prevBtn").style.display = "none";
          }

          if (document.getElementById("saveBtn") != null) {
            document.getElementById("saveBtn").style.display =
              "none";
          }

          scrollWithOffset();

          return false;
        } else {
          showTab(currentTab, prev);
        }
      },
      error: function (xhr, textStatus, errorThrown) {
        console.error(xhr, textStatus, errorThrown);

        Swal.fire({
          icon: "error",
          title: "Oups, quelque chose s'est mal passé!",
          text: "Nous avons rencontré un problème lors de la connexion au service tiers. Malheureusement, nous n'avons pas pu récupérer vos données pour le moment. Veuillez réessayer ultérieurement.",
          showCloseButton: true,
          confirmButtonText: 'Réessayer',
          customClass: {
            confirmButton: 'btn btn-primary'
          },
          buttonsStyling: false
        }).then((result) => {
          if (result.isConfirmed) {
            // Modify the URL to include the fragment identifier and reload
            window.location.href = window.location.href.split('#')[0] + "#formSection";
            window.location.reload();
          }
        });
      },
      complete: function () {
        $(".flexible-form .btn").removeClass("disabled");
        $(btn).removeClass("btn-loading");
      }
    });
  }

  var hiddenToastElement = document.getElementById("hiddentoast");

  if (hiddenToastElement) {
    const messageElements = hiddenToastElement.querySelectorAll(".Message");

    messageElements.forEach((element) => {
      element.classList.add("d-none");
    });
  }

  var spansave = document.getElementsByClassName("spansaveetape");

  Array.prototype.forEach.call(spansave, function (el, index) {
    if (index == currentTab) {
      spanmsave = el;

      if (spanmsave.innerText != null && spanmsave.innerText != "") {
        if (spanmsave.innerText) {
          register = "true";
        }
      }
    }
  });

  var formEtapeQuestions = {};
  var formEtapeQuestionsType = {};
  var formEtapeRecap = {};
  var sendemail = "false";

  // This function will figure out which tab to display
  var x = document.getElementsByClassName("tab");

  if (n == 1) {
    var icalOptions = [];
    var radioOptions = [];
    var checkOptions = [];
    var listOptions = [];
    var listOptionsLabels = [];
    var radioOptionsLabels = [];
    var icalOptionsLabels = [];
    var checkOptionsLabels = [];
    var listOptionImage = [];
    var icalOptionImage = [];
    var radioOptionImage = [];
    var checkOptionImage = [];
    var checkRes = [];
    var checkResList = [];
    var formEtapeQuestionsIcal = {};
    var formEtapeQuestionsRadio = {};
    var formEtapeQuestionsCheck = {};
    var formEtapeQuestionsList = {};
    var selected_input = ".step" + (currentTab + 1);
    var input = $(selected_input + " input");
    var select = $(selected_input + " select");
    var textarea = $(selected_input + " textarea");

    for (i = 0; i < textarea.length; i++) {
      var formEtapeQuestions = {};
      formEtapeQuestions["type"] = "textarea";
      formEtapeQuestions["options"] = "";
      formEtapeQuestions["optionslabel"] = "";
      formEtapeQuestions["optionsUnite"] = "";
      formEtapeQuestions["recap-id"] = "";
      formEtapeQuestions["optionsImage"] = "";
      formEtapeQuestions["imageHttpServer"] = "";
      formEtapeQuestions["reponse"] = textarea[i].value;
      formEtapeQuestionsType[textarea[i].name] = formEtapeQuestions;
    }

    for (i = 0; i < input.length; i++) {
      if (
        input[i].type == "number" ||
        input[i].type == "text" ||
        input[i].type == "email" ||
        input[i].type == "tel"
      ) {
        if (input[i].hasAttribute("list")) {
          inputlabel = "";
          inputlabel = input[i].getAttribute("data-option-value");
          inputunitelabel = input[i].getAttribute("data-option-unite");
          inputimage = input[i].getAttribute("data-option-image");
          inputimageserver = input[i].getAttribute("data-option-image-server");
          if (
            formEtapeQuestionsType.hasOwnProperty(
              input[i].getAttribute("data-name")
            ) == false
          ) {
            var formEtapeQuestionsList = {};
            listOptions = [input[i].getAttribute("data-option")];
            listOptionsLabels = [inputlabel];
            listOptionImage = [inputimage];
            listOptionImageServer = [inputimageserver];
            formEtapeQuestionsList["options"] = listOptions;
            formEtapeQuestionsList["optionslabel"] = listOptionsLabels;
            formEtapeQuestionsList["optionsImage"] = listOptionImage;
            formEtapeQuestionsList["imageHttpServer"] = listOptionImageServer;

            checkResList = [input[i].value];
          } else {
            listOptions.push(input[i].getAttribute("data-option"));
            listOptionsLabels.push(inputlabel);
            listOptionImage.push(inputimage);
            listOptionImageServer.push(inputimageserver);
            formEtapeQuestionsList["options"] = listOptions;
            formEtapeQuestionsList["optionslabel"] = listOptionsLabels;
            formEtapeQuestionsList["optionsImage"] = listOptionImage;
            formEtapeQuestionsList["imageHttpServer"] = listOptionImageServer;
            checkResList.push(input[i].value);
          }

          formEtapeQuestionsList["type"] = "list";
          formEtapeQuestionsList["optionsUnite"] = inputunitelabel;
          formEtapeQuestionsList["recap-id"] =
            input[i].getAttribute("data-recap-id");
          formEtapeQuestionsList["reponse"] = checkResList;
          formEtapeQuestionsType[input[i].getAttribute("data-name")] =
            formEtapeQuestionsList;
        } else {
          if (
            input[i].id != "text-validate-code-email" &&
            input[i].id != "text-validate-code-sms"
          ) {
            var formEtapeQuestions = {};
            formEtapeQuestions["type"] = input[i].type;
            formEtapeQuestions["recap-id"] = "";
            formEtapeQuestions["options"] = "";
            formEtapeQuestions["optionslabel"] = "";
            formEtapeQuestions["optionsUnite"] = "";
            formEtapeQuestions["optionsImage"] = "";
            formEtapeQuestions["imageHttpServer"] = "";
            formEtapeQuestions["reponse"] = input[i].value;
            formEtapeQuestionsType[input[i].getAttribute("data-name")] =
              formEtapeQuestions;

            if (input[i] && input[i].getAttribute("data-champ-id") && input[i].getAttribute("data-champ-id").includes("contact_")) {

              formEtapeQuestions["type"] = "contact_";
              formEtapeQuestions["recap-id"] = "";
              formEtapeQuestions["options"] = "";
              formEtapeQuestions["optionslabel"] = "";
              formEtapeQuestions["optionsUnite"] = "";
              formEtapeQuestions["optionsImage"] = "";
              formEtapeQuestions["imageHttpServer"] = "";
              formEtapeQuestions["reponse"] = input[i].value;
              // checkOptions.push(input[i].value);
              namecontact =
                input[i].getAttribute("data-champ-id") + " contact_";
              formEtapeQuestionsType[input[i].getAttribute("data-champ-id")] =
                formEtapeQuestions;
            }

            if (
              input[i] &&
              input[i].getAttribute("data-champ-id")
            ) {
              formEtapeQuestions["type"] = "entreprise_";
              formEtapeQuestions["recap-id"] = "";
              formEtapeQuestions["options"] = "";
              formEtapeQuestions["optionslabel"] = "";
              formEtapeQuestions["optionsUnite"] = "";
              formEtapeQuestions["optionsImage"] = "";
              formEtapeQuestions["imageHttpServer"] = "";
              formEtapeQuestions["reponse"] = input[i].value;
              // checkOptions.push(input[i].value);
              nameentreprise =
                input[i].getAttribute("data-champ-id") + " entreprise_";
              formEtapeQuestionsType[input[i].getAttribute("data-champ-id")] =
                formEtapeQuestions;
            }

            if (
              input[i].hasAttribute("data-type") &&
              input[i].getAttribute("data-type") == "ical_day"
            ) {
              let inputlabel = input[i].getAttribute("data-option-value");
              let inputimage = input[i].getAttribute("data-option-image");
              let inputimageserver = input[i].getAttribute(
                "data-option-image-server"
              );

              icalOptions.push(input[i].value);
              icalOptionsLabels.push(inputlabel);
              icalOptionImage.push(inputimage);
              let icalOptionImageServer = [inputimage];
              formEtapeQuestionsIcal["options"] = "";
              formEtapeQuestionsIcal["optionslabel"] = "";
              formEtapeQuestionsIcal["optionsUnite"] = "";
              formEtapeQuestionsIcal["optionsImage"] = "";
              formEtapeQuestionsIcal["imageHttpServer"] = "";

              if (input[i].value) {
                formEtapeQuestionsIcal["reponse"] = input[i].value;
              }

              formEtapeQuestionsIcal["type"] =
                input[i].getAttribute("data-type");
              formEtapeQuestionsIcal["unit-price"] =
                input[i].getAttribute("data-unit-price");
              formEtapeQuestionsIcal["total-days"] =
                input[i].getAttribute("data-total-days");
              formEtapeQuestionsIcal["type-reservation"] = input[
                i
              ].getAttribute("data-type-reservation");
              formEtapeQuestionsIcal["recap-id"] =
                input[i].getAttribute("data-recap-id");
              formEtapeQuestionsIcal["etat"] =
                input[i].getAttribute("data-etat");
              formEtapeQuestionsType[input[i].getAttribute("data-name")] =
                formEtapeQuestionsIcal;
            }

            // Remove existing captcha entry from 'formEtapeQuestionsType' if data-type="captcha"
            if (
              input[i].hasAttribute("data-type") &&
              input[i].getAttribute("data-type") === "captcha"
            ) {
              delete formEtapeQuestionsType[input[i].getAttribute("data-name")];
            }

            // Create a fresh object for captcha if data-champ-id includes "captcha"
            if (
              input[i] &&
              input[i].getAttribute("data-champ-id") &&
              input[i].getAttribute("data-champ-id").includes("captcha")
            ) {
              let formEtapeQuestionsCaptchaID = {};
              var cookieName = input[i].getAttribute('data-form-id') + '_' + input[i].getAttribute("data-champ-id");

              // Set desired properties
              formEtapeQuestionsCaptchaID["type"] = "captcha";
              formEtapeQuestionsCaptchaID["cookie_name"] = cookieName;
              formEtapeQuestionsCaptchaID["reponse"] = input[i].value;

              // Save under data-champ-id as key
              formEtapeQuestionsType[input[i].getAttribute("data-champ-id")] = formEtapeQuestionsCaptchaID;
            }

          }
        }
      } else if (input[i].type == "radio") {
        inputlabel = "";
        inputlabel = input[i].getAttribute("data-option-value");
        inputimage = input[i].getAttribute("data-option-image");
        inputimageserver = input[i].getAttribute("data-option-image-server");
        if (
          formEtapeQuestionsType.hasOwnProperty(
            input[i].getAttribute("data-name")
          ) == false
        ) {
          var formEtapeQuestionsRadio = {};
          formEtapeQuestionsRadio["reponse"] = "";
          radioOptions = [input[i].value];
          radioOptionsLabels = [inputlabel];
          radioOptionImage = [inputimageserver];
          radioOptionImageServer = [inputimage];
          formEtapeQuestionsRadio["options"] = radioOptions;
          formEtapeQuestionsRadio["optionslabel"] = radioOptionsLabels;
          formEtapeQuestionsRadio["optionsUnite"] = "";
          formEtapeQuestionsRadio["optionsImage"] = radioOptionImage;
          formEtapeQuestionsRadio["imageHttpServer"] = radioOptionImageServer;
        } else {
          radioOptions.push(input[i].value);
          radioOptionsLabels.push(inputlabel);
          radioOptionImage.push(inputimage);
          radioOptionImageServer.push(inputimageserver);
          formEtapeQuestionsRadio["options"] = radioOptions;
          formEtapeQuestionsRadio["optionslabel"] = radioOptionsLabels;
          formEtapeQuestionsRadio["optionsUnite"] = "";
          formEtapeQuestionsRadio["optionsImage"] = radioOptionImage;
          formEtapeQuestionsRadio["imageHttpServer"] = radioOptionImageServer;
        }

        if (input[i].checked) {
          formEtapeQuestionsRadio["reponse"] = input[i].value;
        }

        formEtapeQuestionsRadio["type"] = input[i].type;
        formEtapeQuestionsRadio["recap-id"] =
          input[i].getAttribute("data-recap-id");
        formEtapeQuestionsType[input[i].getAttribute("data-name")] =
          formEtapeQuestionsRadio;
      } else if (input[i].type == "checkbox") {
        inputlabel = "";
        inputlabel = input[i].getAttribute("data-option-value");
        inputimage = input[i].getAttribute("data-option-image");
        inputimageserver = input[i].getAttribute("data-option-image-server");
        if (
          formEtapeQuestionsType.hasOwnProperty(
            input[i].getAttribute("data-name")
          ) == false
        ) {
          var formEtapeQuestionsCheck = {};
          checkOptions = [input[i].value];
          checkOptionsLabels = [inputlabel];
          checkOptionImage = [inputimage];
          checkOptionImageServer = [inputimageserver];
          formEtapeQuestionsCheck["options"] = checkOptions;
          formEtapeQuestionsCheck["optionslabel"] = checkOptionsLabels;
          formEtapeQuestionsCheck["optionsUnite"] = "";
          formEtapeQuestionsCheck["optionsImage"] = checkOptionImage;
          formEtapeQuestionsCheck["imageHttpServer"] = checkOptionImageServer;
          if (input[i].checked) {
            checkRes = [input[i].value];
          }
        } else {
          checkOptions.push(input[i].value);
          checkOptionsLabels.push(inputlabel);
          checkOptionImage.push(inputimage);
          checkOptionImageServer.push(inputimageserver);
          formEtapeQuestionsCheck["options"] = checkOptions;
          formEtapeQuestionsCheck["optionslabel"] = checkOptionsLabels;
          formEtapeQuestionsCheck["optionsUnite"] = "";
          formEtapeQuestionsCheck["optionsImage"] = checkOptionImage;
          formEtapeQuestionsCheck["imageHttpServer"] = checkOptionImageServer;
          if (input[i].checked) {
            checkRes.push(input[i].value);
          }
        }

        formEtapeQuestionsCheck["type"] = input[i].type;
        formEtapeQuestionsCheck["recap-id"] =
          input[i].getAttribute("data-recap-id");
        formEtapeQuestionsCheck["reponse"] = checkRes;
        formEtapeQuestionsType[input[i].getAttribute("data-name")] =
          formEtapeQuestionsCheck;
      } else if (input[i].type == "hidden") {
        if (input[i].id == "formetapequestion") {
          formTitleEtape[input[i].value] = formEtapeQuestionsType;
        } else if (
          input[i].id == "formlabelrecap" ||
          input[i].id == "formlabelrecapid" ||
          input[i].id == "formlabelrecapunit" ||
          input[i].id == "nomVariableRecap" ||
          input[i].id == "encaissementEnLigne"
        ) {
          if (input[i].id == "formlabelrecap") {
            // recapLabel.unshift(input[i].value);
            recapLabel.push(input[i].value);
            formEtapeRecap["recap-label"] = recapLabel;
          } else if (input[i].id == "formlabelrecapid") {
            recapId.push(input[i].value);
            resrecap = document.getElementById("resAddition-" + input[i].value);
            recapResAdd.push(resrecap.innerText);
            formEtapeRecap["recap-id"] = recapId;
            formEtapeRecap["recap-res"] = recapResAdd;
          } else if (input[i].id == "formlabelrecapunit") {
            recapUnite.push(input[i].value);
            formEtapeRecap["recap-unite"] = recapUnite;
          } else if (input[i].id == "nomVariableRecap") {
            nomVariable.push(input[i].value);
            formEtapeRecap["recap-nom-variable"] = nomVariable;
          } else if (input[i].id == "encaissementEnLigne") {
            encaissement = input[i].value;
            formEtapeRecap["recap-encaissement-en-ligne"] = encaissement;
          }
          // reversed = array1.reverse();
          formTitleEtape["recap"] = formEtapeRecap;
        }
      } else if (input[i].type === "file") {
        const fieldKey = input[i].dataset.name || input[i].name;   // "This is a file field"

        // Grab every hidden input FilePond injected for this field
        const urls = [...document.querySelectorAll(`input[name="${fieldKey}"]`)]
          .map(h => h.value)
          .filter(Boolean);

        formEtapeQuestionsType[fieldKey] = {
          type: "file",
          "recap-id": input[i].dataset.recapId || "",
          options: [], optionslabel: [], optionsUnite: "",
          optionsImage: [], imageHttpServer: [],
          reponse: urls              // <-- now filled
        };
      }
    }

    for (i = 0; i < select.length; i++) {
      const selectElement = select[i];
      const inputName = selectElement.getAttribute("data-name");

      if (inputName) {
        // Initialize or retrieve the object to store select input details
        const formEtapeQuestionsSelect = formEtapeQuestionsType[inputName] || {
          type: "select",
          options: [],
          optionslabel: [],
          optionsImage: [],
          imageHttpServer: [],
          optionsUnite: selectElement.getAttribute("data-option-unite") || "",
          "recap-id": selectElement.getAttribute("data-recap-id") || "",
          reponse: "" // Store only the selected option's text here
        };

        // Iterate over each option in the select element
        $(selectElement).find("option").each((index, option) => {
          // Skip disabled options
          if (option.disabled) {
            return;
          }

          // Get the option text and value
          const optionText = option.value.trim();
          const optionValue = option.getAttribute("data-option-value") || "";
          const optionImage = option.getAttribute("data-option-image") || "";
          const optionImageServer = option.getAttribute("data-option-image-server") || "";

          // Add the option text to the `options` array
          formEtapeQuestionsSelect.options.push(optionText);

          // Add the option value to the `optionslabel`
          formEtapeQuestionsSelect.optionslabel.push(optionValue);

          // Add the option value to the `optionsImage`
          formEtapeQuestionsSelect.optionsImage.push(optionImage);

          // Add the option value to the `imageHttpServer`
          formEtapeQuestionsSelect.imageHttpServer.push(optionImageServer);
        });

        // Set the selected option's text in the `reponse` key
        formEtapeQuestionsSelect.reponse = $(selectElement).find("option:selected").val().trim();

        // Assign the updated object back to formEtapeQuestionsType
        formEtapeQuestionsType[inputName] = formEtapeQuestionsSelect;
      }
    }

    /* formEtapeQuestions */

    /* formTitleEtape[$('#formetapequestion').val()] = formEtapeQuestionsType; */

    resRecapId = [];
    resRecapLabel = [];
    resRecapRes = [];
    resRecapUnite = [];
    resPayment = [];
    nomVariablePhpRecap = [];
    encaissementEnLigne = "";
    if (typeof formTitleEtape["recap"] !== "undefined") {
      if (typeof formTitleEtape["recap"]["recap-label"] !== "undefined") {
        // reczetp = formTitleEtape['recap'];

        indexdup = findDublicatesNumbersFromArray(
          formTitleEtape["recap"]["recap-label"]
        );

        if (indexdup.length > 0) {
          // indexdup.pop();
          indexdup.forEach(function (index) {
            if (typeof formTitleEtape["recap"]["recap-label"] !== "undefined") {
              resRecapId.push(formTitleEtape["recap"]["recap-id"][index]);
              resRecapLabel.push(formTitleEtape["recap"]["recap-label"][index]);
              resRecapRes.push(formTitleEtape["recap"]["recap-res"][index]);
              resRecapUnite.push(formTitleEtape["recap"]["recap-unite"][index]);
              if (
                typeof formTitleEtape["recap"]["recap-nom-variable"] !==
                "undefined"
              ) {
                nomVariablePhpRecap.push(
                  formTitleEtape["recap"]["recap-nom-variable"][index]
                ); // nom_variable php du recap
              }

              encaissementEnLigne =
                formTitleEtape["recap"]["recap-encaissement-en-ligne"];
            }
          });
        }
      }

      formTitleEtape["recap"]["recap-id"] = resRecapId;
      formTitleEtape["recap"]["recap-label"] = resRecapLabel;
      formTitleEtape["recap"]["recap-res"] = resRecapRes;
      formTitleEtape["recap"]["recap-unite"] = resRecapUnite;
      formTitleEtape["recap"]["recap-payment-result"] = resPayment;
      formTitleEtape["recap"]["recap-nom-variable"] = nomVariablePhpRecap;
      formTitleEtape["recap"]["recap-encaissement-en-ligne"] =
        encaissementEnLigne;
      formTitleEtape["recap"]["recap-url-paiement"] = "";
    }

    formTitleJson[$("#title_form").val()] = formTitleEtape;
    curtab = currentTab + n;
    if (curtab >= x.length) {
      sendemail = "true";
      register = "true";
    }

    if (!validateForm()) {
      $(".flexible-form .btn").removeClass("disabled");
      $(btn).removeClass("btn-loading");
      return false;
    }

    if (register == "true") {
      saveForm();
    } else {
      x[currentTab].style.display = "none";
      currentTab = currentTab + n;
      showTab(currentTab, prev);
    }

  } else {
    x[currentTab].style.display = "none";

    currentTab = currentTab + n;
    showTab(currentTab, prev);
  }
}

function insertValidationMessage(inputElement, messageText) {
  var $input = $(inputElement);
  var $parentInputGroup = $input.closest('.form-group');

  if ($parentInputGroup.length > 0) {
    // Always ensure the .required-group class is applied when there's an error
    $parentInputGroup.addClass('required-group');

    var $existingValidationMessage = $parentInputGroup.find('.error-msg');
    if ($existingValidationMessage.length > 0) {
      $existingValidationMessage.text("");
      setTimeout(function () {
        $existingValidationMessage.text(messageText);
      }, 50);
    } else {
      var $small = $('<small class="text-danger error-msg"></small>').text(messageText);
      $parentInputGroup.append($small);
    }
  } else {
    // Fallback if there's no .form-group
    var $small = $('<small class="text-danger error-msg"></small>').text(messageText);
    $input.after($small);
    $input.parent().addClass('required-group');
  }
}

function validateForm() {
  function validateFilePondField(inputElement) {
    const pondElement = inputElement.closest('.filepond--root');
    if (!pondElement) return false;

    const pond = FilePond.find(pondElement);
    if (!pond) return false;

    const files = pond.getFiles();

    // Check if there are files and none have errors
    const hasValidFiles = files.length > 0 &&
      !files.some(file => file.status === FilePond.FileStatus.LOAD_ERROR ||
        file.status === FilePond.FileStatus.PROCESSING_ERROR);

    return hasValidFiles;
  }

  // This function deals with validation of the form fields
  var x, y, i, valid = true;
  x = document.getElementsByClassName("tab");

  // Get all <input> elements in the current tab
  var inputs = x[currentTab].getElementsByTagName("input");

  // Get all <textarea> elements in the current tab
  var textareas = x[currentTab].getElementsByTagName("textarea");

  // Get all <select> elements in the current tab
  var selects = x[currentTab].getElementsByTagName("select");

  // Combine them into a single array "y"
  var y = Array.from(inputs)
    .concat(Array.from(textareas))
    .concat(Array.from(selects));

  // A loop that checks every field (input, textarea, select) in the current tab:
  for (i = 0; i < y.length; i++) {

    // 1) EMAIL FORMAT CHECK
    if (y[i].value != "" && y[i].type == "email") {
      var validRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!y[i].value.match(validRegex)) {
        if (!y[i].classList.contains("invalid")) {
          y[i].className += " invalid";
        }
        insertValidationMessage(y[i], 'Veuillez saisir une adresse email valide.');
        valid = false;
      } else {
        y[i].classList.remove("invalid");
      }
    }

    // 2) PHONE FORMAT CHECK
    else if (y[i].value != "" && y[i].type == "tel") {
      var validRegexPhone = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im;
      if (!y[i].value.match(validRegexPhone)) {
        if (!y[i].classList.contains("invalid")) {
          y[i].className += " invalid";
        }
        insertValidationMessage(y[i], 'Veuillez confirmer le numéro saisi.');
        valid = false;
      } else {
        y[i].classList.remove("invalid");
      }
    }

    // 3) NUMBER FORMAT CHECK FOR REQUIRED NUMBER FIELDS
    else if (y[i].type === "number" && y[i].hasAttribute("required")) {
      // find the wrapping <div class="form-check-group"> for this input
      var group = y[i].closest('.form-check-group');
      if (!group) {
        // no wrapper → fall back to the old per‑input behavior
        var re = /^-?\d+(\.\d+)?$/im;
        if (!re.test(y[i].value)) {
          y[i].classList.add("invalid");
          insertValidationMessage(y[i], 'Veuillez insérer un numéro valide');
          valid = false;
        } else {
          y[i].classList.remove("invalid");
        }
      } else {
        // only do the group check once
        if (!group.dataset.checked) {
          group.dataset.checked = '1';
          var nums = Array.from(group.querySelectorAll('input[type="number"]'));
          var re = /^-?\d+(\.\d+)?$/im;
          // any one field both non‑empty AND matching the regex?
          var anyGood = nums.some(function (inp) {
            return inp.value.trim() !== '' && re.test(inp.value);
          });

          if (anyGood) {
            // clear any old errors
            nums.forEach(function (inp) {
              inp.classList.remove("invalid");
              var old = inp.closest('.form-group')?.querySelector('.error-msg');
              if (old) old.remove();
            });
          } else {
            // mark all invalid and show message on each
            valid = false;
            nums.forEach(function (inp) {
              inp.classList.add("invalid");
              insertValidationMessage(
                inp,
                'Veuillez insérer un numéro valide'
              );
            });
          }
        }
      }
    }

    else if (y[i].type === "file" && y[i].hasAttribute("required")) {
      const hasValidFiles = validateFilePondField(y[i]);

      if (!hasValidFiles) {
        if (!y[i].classList.contains("invalid")) {
          y[i].className += " invalid";
        }
        insertValidationMessage(y[i], "Veuillez téléverser au moins un fichier valide.");
        valid = false;
      } else {
        y[i].classList.remove("invalid");
        y[i].closest(".form-group").classList.remove('required-group');
      }
      continue;
    }

    // 4) GENERIC REQUIRED FIELD CHECK (INPUT, TEXTAREA, SELECT, ETC.)
    else if (y[i].hasAttribute("required")) {
      if (y[i].value == "") {
        // Mark as invalid if empty
        if (!y[i].classList.contains("invalid")) {
          y[i].className += " invalid";
        }
        insertValidationMessage(y[i], 'Veuillez renseigner ce champ');
        valid = false;

        // --- NEW LOGIC FOR <select> (TomSelect) ---
        // If it's a SELECT, also update the .ts-wrapper
        if (y[i].tagName === "SELECT") {

          // Get the next sibling element in the DOM
          let tsWrapper = y[i].nextElementSibling;

          // Ensure that next sibling exists and has the "ts-wrapper" class
          if (tsWrapper && tsWrapper.classList.contains('ts-wrapper')) {
            // Remove "to-validate" if present
            tsWrapper.classList.remove('to-validate');

            // Add "invalid" if not already there
            if (!tsWrapper.classList.contains('invalid')) {
              tsWrapper.classList.add('invalid');
            }
          }
        }
      } else {
        // If not empty, remove 'invalid' before additional checks
        y[i].classList.remove("invalid");

        // If it's a SELECT, remove invalid from .ts-wrapper as well
        if (y[i].tagName === "SELECT") {
          // Get the immediate next sibling
          const tsWrapper = y[i].nextElementSibling;

          // Make sure it exists and has class "ts-wrapper"
          if (tsWrapper && tsWrapper.classList.contains('ts-wrapper')) {
            tsWrapper.classList.remove('invalid');
          }
        }

        // Additional checks if it's email again
        if (y[i].type == "email") {
          var validRegex2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
          if (!y[i].value.match(validRegex2)) {
            if (!y[i].classList.contains("invalid")) {
              y[i].className += " invalid";
            }
            insertValidationMessage(y[i], 'Veuillez entrer une adresse email valide.');
            valid = false;
          } else {
            y[i].classList.remove("invalid");
          }
        }

        // Additional checks if it's tel again
        else if (y[i].type == "tel") {
          var validRegexTel = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im;
          if (!y[i].value.match(validRegexTel)) {
            if (!y[i].classList.contains("invalid")) {
              y[i].className += " invalid";
            }
            insertValidationMessage(y[i], 'Veuillez vérifier le numéro saisi.');
            valid = false;
          } else {
            y[i].classList.remove("invalid");
          }
        }

        // Required RADIO check
        else if (y[i].type == "radio") {
          if (!$("input[name=" + y[i].name + "]").is(":checked")) {
            if (!y[i].classList.contains("invalid")) {
              y[i].className += " invalid";
            }
            insertValidationMessage(y[i], 'Veuillez choisir l\'une de ces options.');
            valid = false;
          } else {
            y[i].classList.remove("invalid");
          }
        }

        // Required CHECKBOX check
        else if (y[i].type == "checkbox") {
          if (!$("input[name=" + y[i].name + "]").is(":checked")) {
            if (!y[i].classList.contains("invalid")) {
              y[i].className += " invalid";
            }
            insertValidationMessage(y[i], 'Veuillez choisir au moins une de ces options.');
            valid = false;
          } else {
            y[i].classList.remove("invalid");
          }
        }

        // "list" type in your original code (not standard HTML)
        else if (y[i].type == "list") {
          if (!$("input[name=" + y[i].name + "]").is(":checked")) {
            if (!y[i].classList.contains("invalid")) {
              y[i].className += " invalid";
            }
            insertValidationMessage(y[i], 'Veuillez choisir au moins une de ces options.');
            valid = false;
          } else {
            y[i].classList.remove("invalid");
          }
        }
      }
    }
  }

  // If the valid status is true, mark the step as finished and valid:
  if (valid) {
    for (i = 0; i < y.length; i++) {
      y[i].classList.remove("invalid");
    }
    var step = document.getElementsByClassName("step");
    if (step.length) {
      step[currentTab].className += " done";
    }
  }

  return valid; // return the valid status
}

function fixStepIndicator(n) {
  // This function removes the "active" class of all steps...
  var i,
    x = document.getElementsByClassName("step");

  if (x.length) {
    for (i = 0; i < x.length; i++) {
      x[i].className = x[i].className.replace(" active", "");
    }
    // ... and adds the "active" class on the current step:
    x[n].className += " active";
  }
}

function sendCode(btn, type, inputName) {
  $(btn).addClass('btn-loading');
  var minput = $("input[name=" + inputName + "]").eq(0); // Use .eq(0) to get the first matching element

  if (type == "email") {
    var validRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!minput.val().match(validRegex)) {
      if (!minput.hasClass("invalid")) {
        minput.addClass("invalid");
      }

      insertValidationMessage(minput, 'Veuillez saisir une adresse email valide.');
      $(btn).removeClass('btn-loading');
    } else {
      minput.closest('.form-group').find('.error-msg').text("");
      minput.removeClass("invalid");
      var codevalue = "";

      $.ajax({
        url: dataJsonForm.send_conf_code,
        type: "POST",
        timeout: 30000,
        data: {
          token: $("#token").val(),
          contact_email_secure: $("#text-contact_email_secure").val(),
          secure: "Email"
        },
        dataType: "json",
        success: function (data) {
          $("#token").val(data.token);
          $("div[name=div-vallidate-code-email]")
            .prop("hidden", false)
            .trigger("visibilitychange");
          $("div[name=div-contact_email_secure]").prop("hidden", true);
          $('#resendEmailLinkCode').hide();
          setVerifyCode('emailCode', data.code);
          var countdown = 30;
          $('#countdownEmailMessage').text('(vous pourrez le renvoyer dans ' + countdown + ' secondes).');

          // Update the countdown every second
          var intervalId = setInterval(function () {
            countdown--;
            $('#countdownEmailMessage').text('(vous pourrez le renvoyer dans ' + countdown + ' secondes).');

            // If countdown is finished, clear the interval and show the link
            if (countdown <= 0) {
              clearInterval(intervalId);
              $('#countdownEmailMessage').text('');
              $("#resendEmailLinkCode").text('Renvoyer le code');
              $("#resendEmailLinkCode").css('pointer-events', 'auto');
              $("#resendEmailLinkCode").show();
            }
          }, 1000);
        },
        error: function (xhr, textStatus, errorThrown) {
          console.error(xhr, textStatus, errorThrown);

          Swal.fire({
            icon: "error",
            title: "Oups, quelque chose s'est mal passé!",
            text: "Nous avons rencontré un problème lors de la connexion au service tiers. Malheureusement, nous n'avons pas pu récupérer vos données pour le moment. Veuillez réessayer ultérieurement.",
            showCloseButton: true,
            confirmButtonText: 'Réessayer',
            customClass: {
              confirmButton: 'btn btn-primary'
            },
            buttonsStyling: false
          }).then((result) => {
            if (result.isConfirmed) {
              window.location.href = window.location.href.split('#')[0] + "#formSection";
              window.location.reload();
            }
          });
        },
        complete: function () {
          $(".flexible-form  .btn").removeClass("disabled");
          $(btn).removeClass("btn-loading");
        }
      });
    }
  } else if (type == "tel") {
    var validRegex = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im;

    if (!minput.val().match(validRegex)) {
      if (!minput.hasClass("invalid")) {
        minput.addClass("invalid");
      }

      insertValidationMessage(minput, 'Veuillez confirmer le numéro saisi.');
      $(btn).removeClass('btn-loading');
    } else {
      minput.parent('.form-group').next('.msg-error').text("");
      minput.removeClass("invalid");

      $.ajax({
        url: dataJsonForm.send_conf_code,
        type: "POST",
        timeout: 30000,
        data: {
          token: $("#token").val(),
          contact_tel_secure: $("#text-contact_tel_secure").val(),
          secure: "SMS"
        },
        dataType: "json",
        success: function (data) {
          $("#token").val(data.token);
          $("div[name=div-vallidate-code-sms]")
            .prop("hidden", false)
            .trigger("visibilitychange");
          $("div[name=div-contact_tel_secure]").prop("hidden", true);
          $('#resendSmsLinkCode').hide();
          setVerifyCode('smsCode', data.code);
          var countdown = 30;
          $('#countdownSmsMessage').text('(vous pourrez le renvoyer dans ' + countdown + ' secondes).');

          // Update the countdown every second
          var intervalId = setInterval(function () {
            countdown--;
            $('#countdownSmsMessage').text('(vous pourrez le renvoyer dans ' + countdown + ' secondes).');

            // If countdown is finished, clear the interval and show the link
            if (countdown <= 0) {
              clearInterval(intervalId);
              $('#countdownSmsMessage').text('');
              $("#resendSmsLinkCode").text('Renvoyer le code');
              $("#resendSmsLinkCode").css('pointer-events', 'auto');
              $("#resendSmsLinkCode").show();
            }
          }, 1000);
        },
        error: function (xhr, textStatus, errorThrown) {
          console.error(xhr, textStatus, errorThrown);

          Swal.fire({
            icon: "error",
            title: "Oups, quelque chose s'est mal passé!",
            text: "Nous avons rencontré un problème lors de la connexion au service tiers. Malheureusement, nous n'avons pas pu récupérer vos données pour le moment. Veuillez réessayer ultérieurement.",
            showCloseButton: true,
            confirmButtonText: 'Réessayer',
            customClass: {
              confirmButton: 'btn btn-primary'
            },
            buttonsStyling: false
          }).then((result) => {
            if (result.isConfirmed) {
              window.location.href = window.location.href.split('#')[0] + "#formSection";
              window.location.reload();
            }
          });
        },
        complete: function () {
          $(".flexible-form  .btn").removeClass("disabled");
          $(btn).removeClass("btn-loading");
        }
      });
    }
  }
}

function verifyCodeEmail() {
  var codevalue = getVerifyCode('emailCode');
  minputCode = $("input[name=text-validate-code-email]")[0];
  /* !minputCode.checkValidity() ||  */
  if (minputCode.value.length != 6) {
    if (!minputCode.classList.contains("invalid")) {
      minputCode.className += " invalid";
    }

    insertValidationMessage(minputCode, 'Veuillez saisir une adresse email valide.');
  } else {
    if (minputCode.value === codevalue.code) {
      minputCode.classList.remove("invalid");
      $("div.inpdiv")
        .not(
          "[name=div-vallidate-code-email], [name=div-contact_email_secure], [name=div-vallidate-code-sms]"
        )
        .prop("hidden", false);

      $("div[name=div-vallidate-code-email]")
        .prop("hidden", true)
        .addClass("validCodeverifyemail");
      $("div[name=div-contact_email_secure]")
        .prop("hidden", true)
        .addClass("validCodeverifyemail");

      // minputCode.classList.add('validCodeverify');
    } else {
      minputCode.classList.add("invalid");
      insertValidationMessage(minputCode, 'Code non valide, veuillez réessayer.');
    }
  }
}

function setVerifyCode(label, code) {
  var expirationTime = 10 * 60 * 1000; // 10 minutes in milliseconds
  var expiresAt = new Date().getTime() + expirationTime;
  localStorage.setItem(label, JSON.stringify({ code: code, expiresAt: expiresAt }));
}

function getVerifyCode(label) {
  var code = JSON.parse(localStorage.getItem(label));
  if (!code) return null;

  var currentTime = new Date().getTime();
  if (currentTime > code.expiresAt) {
    localStorage.removeItem(label); // Remove expired code
    return null;
  }

  return code;
}

function verifyCodeSMS(btn) {
  var codevalue = getVerifyCode('smsCode');
  $(btn).addClass('btn-loading');
  minputCode = $("input[name=text-validate-code-sms]")[0];
  if (minputCode.value.length != 6) {
    if (!minputCode.classList.contains("invalid")) {
      minputCode.className += " invalid";
    }

    insertValidationMessage(minputCode, 'Veuillez vérifier le numéro saisi.');
    $(btn).removeClass('btn-loading');
  } else {
    if (minputCode.value === codevalue.code) {
      minputCode.classList.remove("invalid");
      $("div.inpdiv")
        .not(
          "[name=div-vallidate-code-sms], [name=div-contact_tel_secure], [name=div-vallidate-code-email]"
        )
        .prop("hidden", false);

      $("div[name=div-vallidate-code-sms]").prop("hidden", true);

      $("div[name=div-vallidate-code-sms]")
        .prop("hidden", true)
        .addClass("validCodeverifysms");
      $("div[name=div-contact_tel_secure]")
        .prop("hidden", true)
        .addClass("validCodeverifysms");
    } else {
      insertValidationMessage(minputCode, 'Code non valide, veuillez réessayer.');
      $(btn).removeClass('btn-loading');
    }
  }
}

function resendCodeEmail(btn) {
  $(btn).text('Envoi en cours...');
  $("#sendEmailCodeBtn").click();
  $(btn).css('pointer-events', 'none');
}

function resendCodeSMS(btn) {
  $(btn).text('Envoi en cours...');
  $("#sendSmsCodeBtn").click();
  $(btn).css('pointer-events', 'none');
}

function telechargerPDF(btn, btnText) {
  $.ajax({
    url: dataJsonForm.download_pdf_link,
    type: "POST",
    timeout: 30000,
    dataType: "json",

    data: {
      token: $("#token").val(),
      form: $("#form").val(),
      title_form: $("#title_form").val(),
    },

    success: function (data) {
      respdf = data.url;
      if (window.location.hostname.includes("192.168.0.210")) {
        respdf = "http://" + window.location.hostname + data.url;
      } else {
        respdf = "https://" + window.location.hostname + data.url;
      }

      hrefg = respdf.replace("/download/pdf", "/PDF") + ".pdf";
      var anchor = document.createElement("a");
      anchor.href = hrefg;
      anchor.download = "Devis.pdf";
      anchor.target = "_blank";
      anchor.dispatchEvent(new MouseEvent("click"));
    },

    error: function (xhr, textStatus, errorThrown) {
      console.error(xhr, textStatus, errorThrown);

      Swal.fire({
        icon: "error",
        title: "Oups, quelque chose s'est mal passé!",
        text: "Nous avons rencontré un problème lors de la connexion au service tiers. Malheureusement, nous n'avons pas pu récupérer vos données pour le moment. Veuillez réessayer ultérieurement.",
        showCloseButton: true,
        confirmButtonText: 'Réessayer',
        customClass: {
          confirmButton: 'btn btn-primary'
        },
        buttonsStyling: false
      }).then((result) => {
        if (result.isConfirmed) {
          // Modify the URL to include the fragment identifier and reload
          window.location.href = window.location.href.split('#')[0] + "#formSection";
          window.location.reload();
        }
      });

    },

    complete: function () {
      $(btn).html(btnText).removeClass("btn-loading");
    },
  });
}

function deletePDF(ttoken) {
  $.ajax({
    url: dataJsonForm.delete_pdf_link,
    type: "POST",
    timeout: 30000,
    data: {
      token: ttoken,
    },
    dataType: "json",
    success: function (data) { },
    error: function (xhr, textStatus, errorThrown) {
      console.error(xhr, textStatus, errorThrown);
    },
  });
}

function findDublicatesNumbersFromArray(arr) {
  var existingItems = {};

  arr.forEach(function (value, index) {
    existingItems[value] = index;
  });

  return Object.values(existingItems);
}

function stripePayment(btn, btnText) {
  var tokenValue = $("#token").val();
  var formValue = $("#form").val();
  var url = document.referrer;
  var titreForm = $("#title_form").val();
  var urlPayment = $("#urlTwigPath").val().replace("__token_placeholder__", tokenValue);
  $.ajax({
    url: urlPayment,
    type: "POST",
    timeout: 30000,
    dataType: "json",

    data: {
      token: tokenValue,
      form: formValue,
      title_form: titreForm,
      test: "click",
    },

    success: function (data) {
      //Perform the redirection
      if (data.msg === "error") {
        Swal.fire({
          icon: "error",
          title: "Oops...",
          text: "le montant à encaisser doit ètre supérieur au montant 50€!",
        });
        //redirect vers demander devis
        //window.location.href = "{{ path('app_get_contact', {'id': '__titreForm_placeholder__'}) }}".replace('__titreForm_placeholder__', titreForm);
      } else if (data.msg === "exception") {
        Swal.fire({
          title: "Oops...",
          html: "Le fournisseur du votre paiement stripe n'est pas joignable pour le moment. <br> Réssayer après <b></b> milliseconds.",
          timer: 6000,
          timerProgressBar: true,
          didOpen: () => {
            Swal.showLoading();
            const b = Swal.getHtmlContainer().querySelector("b");
            timerInterval = setInterval(() => {
              b.textContent = Swal.getTimerLeft();
            }, 100);
          },
          willClose: () => {
            clearInterval(timerInterval);
          },
        }).then((result) => {
          /* Read more about handling dismissals below */
          if (result.dismiss === Swal.DismissReason.timer) {
            window.location = document.referrer;
            window.location = document.referrer;
          }
        });
      } else {
        //redirect vers le site de paiement
        window.location.href = data.link;
      }
    },

    error: function (xhr, textStatus, errorThrown) {
      console.error(xhr, textStatus, errorThrown);

      Swal.fire({
        icon: "error",
        title: "Oups, quelque chose s'est mal passé!",
        text: "Nous avons rencontré un problème lors de la connexion au service tiers. Malheureusement, nous n'avons pas pu récupérer vos données pour le moment. Veuillez réessayer ultérieurement.",
        showCloseButton: true,
        confirmButtonText: 'Réessayer',
        customClass: {
          confirmButton: 'btn btn-primary'
        },
        buttonsStyling: false
      }).then((result) => {
        if (result.isConfirmed) {
          // Modify the URL to include the fragment identifier and reload
          window.location.href = window.location.href.split('#')[0] + "#formSection";
          window.location.reload();
        }
      });
    },

    complete: function () {
      $(btn).html(btnText).removeClass("btn-loading");
    },
  });
}

function setupReservationPicker() {
  var changeDtoP = false;
  dataJsonForm.ical_data.forEach(function (element) {
    var icsEventsToDisable = element.icsEventsToDisable;
    var icalAttributes = element.icalAttributes;
    var ical_type_reservation = icalAttributes.ical_type_reservation; // Une chaîne représentant le type de réservation (par exemple, "nuitée" ou "journée").
    var ical_valeur = 0;
    if (icalAttributes.ical_valeur != "") {
      ical_valeur = parseFloat(icalAttributes.ical_valeur);
    }
    // Un entier représentant la valeur associée à chaque jour sélectionné
    var ical_intervalle_min = parseInt(icalAttributes.ical_intervalle_min); // intervalle min
    var ical_intervalle_max = parseInt(icalAttributes.ical_intervalle_max); // intervalle max
    var ical_nb_mois = parseInt(icalAttributes.ical_nb_mois); // nombre de mois
    if ((ical_intervalle_max == ical_intervalle_min == 1) && (ical_type_reservation == "journée")) {
      changeDtoP = true;
    }
    $(function () {
      $('.ical-daterangepicker').daterangepicker({ // Initialise le sélecteur de plage de dates sur les éléments avec la classe "ical-daterangepicker".
        isInvalidDate: function (date) { // fonction vérifie si une date donnée doit être désactivée en fonction des plages dans icsEventsToDisableet du sélectionné ical_type_reservation.
          for (var i = 0; i < icsEventsToDisable.length; i++) {
            var range = icsEventsToDisable[i];
            var start = moment(range.start, "YYYYMMDD");
            var end = moment(range.end, "YYYYMMDD");
            if (ical_type_reservation == "nuitée") {
              if (date.isBetween(start, end, null, '[)')) {
                return true;
              }
            } else if (ical_type_reservation == "journée") {
              if (date.isBetween(start, end, null, '[]')) {
                return true;
              }
            }
          }
          return false;
        },
        singleDatePicker: changeDtoP,
        // singleDatePicker: true,
        "locale": {
          // Définit les paramètres de localisation du sélecteur de plage de dates(format,nb_jours,nb_mois)
          "format": "DD/MM/YYYY",
          "separator": " - ",
          "applyLabel": "Appliquer",
          "cancelLabel": "Annuler",
          "fromLabel": "De",
          "toLabel": "À",
          "customRangeLabel": "Custom",
          "weekLabel": "W",
          "daysOfWeek": [
            "dim",
            "lun",
            "mar",
            "mer",
            "jeu",
            "ven",
            "sam"
          ],
          "monthNames": [
            "janvier",
            "février",
            "mars",
            "avril",
            "mai",
            "juin",
            "juillet",
            "août",
            "septembre",
            "octobre",
            "novembre",
            "décembre"
          ],
          "firstDay": 1
        },
        "dateLimit": {
          "days": ical_nb_mois * 30
        }
      }).on('apply.daterangepicker', function (ev, picker) {
        var start = picker.startDate;
        var end = picker.endDate;
        var valide = true;
        // Ajoutez un jour à la date de fin pour les réservations de type "nuitée"
        if ((ical_type_reservation == "nuitée")) {
          if (start.isSame(end, 'day')) {
            Swal.fire({ icon: 'error', title: 'Oops...', text: "La plage minimale de sélection d'une nuitée est 2 jours" });
            picker.setStartDate(moment().subtract(ical_intervalle_max, 'days'));
            picker.setEndDate(moment());
            valide = false;
          } else {
            end = end.subtract(1, 'days');
          }
        }
        var dayDiff = end.diff(start, 'days');
        var daysCount = end.diff(start, 'days') + 1;
        if (dayDiff < ical_intervalle_min) {
          if ((daysCount < ical_intervalle_min)) {
            Swal.fire({
              icon: 'error',
              title: 'Oops...',
              text: "La plage minimale de sélection est de " + ical_intervalle_min + " jours"
            });
            picker.setStartDate(moment().subtract(ical_intervalle_max, 'days'));
            picker.setEndDate(moment());
            valide = false;
          }
        }
        // if (dayDiff > ical_intervalle_max) {
        if ((daysCount > ical_intervalle_max)) {
          Swal.fire({
            icon: 'error',
            title: 'Oops...',
            text: "La plage maximale de sélection est de " + ical_intervalle_max + " jours"
          });
          picker.setStartDate(moment().subtract(ical_intervalle_max, 'days'));
          picker.setEndDate(moment());
          valide = false;
        }
        // }
        // Calculez le prix total
        // var total_price = dayDiff*ical_valeur;
        var total_price = 0;
        var total_days = 0;
        var day = start.clone();
        // Display the selected date range
        var icalDayValue = $('[data-type="ical_day"]').val();
        while (day.isBefore(end)) {
          // Vérifiez si le jour est invalide
          var isInvalid = false;
          for (var i = 0; i < icsEventsToDisable.length; i++) {
            var range = icsEventsToDisable[i];
            var startRange = moment(range.start, "YYYYMMDD");
            var endRange = moment(range.end, "YYYYMMDD");
            if (ical_type_reservation == "nuitée") {
              if (day.isBetween(startRange, endRange, null, '[)')) {
                isInvalid = true;
                break;
              }
            } else if (ical_type_reservation == "journée") {
              if (day.isBetween(startRange, endRange, null, '[]')) {
                isInvalid = true;
                break;
              }
            }
          }
          if (!isInvalid) {
            total_days += 1;
            total_price += ical_valeur;
          }
          day = day.add(1, 'days');
        }
        var recap_id = parseInt($(this).data("recap-id"));
        var cardBody = $("#cardbody" + recap_id);
        $("#notSelected" + recap_id).hide();

        cardBody.find('.card-item.card-item--ical').remove();
        cardBody.append('<div class="card-item card-item--ical"><div  id="date-text" class="card-text"></div><div  id="date-formule" class="card-unit"></div></div>');

        if (valide) {
          $("#date-text").text(icalDayValue);
          if (ical_valeur >= 0) {
            $("#date-formule").text(total_days + " * " + ical_valeur + " = " + (total_days * ical_valeur).toFixed(2));
          }
        }

        $(this).attr('data-total-days', total_days);
        $(this).attr('data-etat', valide);

        updateTotal();
      });
    });
  });
}

if (document.getElementById("mainFlexibleForm") !== null) {
  document.getElementById("mainFlexibleForm").reset();
  showTab(currentTab, ""); // Display the current tab
}

$(document).ready(function () {
  $(document).on("click", "#toStripe", function () {
    stripePayment($(this), $(this).html());
    $(this).html('<i class="fa fa-refresh fa-spin"></i> Chargement...').addClass("btn-loading");
  });

  $(document).on("click", "#quotePDF", function () {
    telechargerPDF($(this), $(this).html());
    $(this).html('<i class="fa fa-refresh fa-spin"></i> Chargement...').addClass("btn-loading");
  });

  // Select all dropdowns with IDs starting with "select-"
  $('.flexible-form select[id^="select-"]').each(function () {
    new TomSelect(this, {
      placeholder: "Sélectionner une option",
      create: false,
      allowEmptyOption: true,
      searchField: ['text'],
      plugins: ['dropdown_input', 'clear_button'],

      // Don't touch "invalid" on init, so we do NOT remove it.
      onInitialize: function () {
        // 1) Disable TomSelect's validity checks so it won't add/remove "invalid".

        this.wrapper.classList.add('to-validate');
        this.refreshValidityState = function () { };

        // 2) Optional but recommended: remove "required" from the hidden input
        //    so TomSelect won't try to do anything with required attributes.
        this.control_input.removeAttribute('required');
      },

      // Make all these callbacks empty or remove them entirely
      // so TomSelect never adds or removes "invalid" after user actions.
      onFocus: function () { },
      onBlur: function () { },
      onChange: function () { }
    });
  });

  // -----------------------------------------------------
  // INIT  — run once on page load
  // -----------------------------------------------------
  window.filePondRegistry = new Map();   // key = data-name (or fallback id)

  /* FilePond plugins */
  FilePond.registerPlugin(
    FilePondPluginFileValidateSize,
    FilePondPluginImagePreview,
    FilePondPluginFileValidateType
  );

  document.querySelectorAll('input[type="file"]').forEach(origInput => {

    // Create FilePond (your existing code)
    const meta = {
      'data-name': origInput.getAttribute('data-name') || '',
      'data-champ-id': origInput.getAttribute('data-champ-id') || '',
      'data-recap-id': origInput.getAttribute('data-recap-id') || '',
      'data-form-id': origInput.getAttribute('data-form-id') || '',
      name: origInput.name || '',
      id: origInput.id || '',
      required: origInput.hasAttribute('required')
    };

    const labelIdle = window.matchMedia('(hover:none) and (pointer:coarse)').matches
      ? 'Télécharger ou prendre une photo'
      : 'Faites glisser vos fichiers ou <span class="filepond--label-action">Parcourir</span>';

    const pond = FilePond.create(origInput, {
      labelIdle: labelIdle,
      labelInvalidField: "Le champ contient des fichiers invalides",
      labelFileWaitingForSize: "En attente de taille",
      labelFileSizeNotAvailable: "Taille non disponible",
      labelFileLoading: "Chargement",
      labelFileLoadError: "Erreur durant le chargement",
      labelFileProcessing: "Traitement",
      labelFileProcessingComplete: "Traitement effectué",
      labelFileProcessingAborted: "Traitement interrompu",
      labelFileProcessingError: "Erreur durant le traitement",
      labelFileProcessingRevertError: "Erreur durant la restauration",
      labelFileRemoveError: "Erreur durant la suppression",
      labelTapToCancel: "appuyer pour annuler",
      labelTapToRetry: "appuyer pour réessayer",
      labelTapToUndo: "appuyer pour revenir en arrière",
      labelButtonRemoveItem: "Retirer",
      labelButtonAbortItemLoad: "Annuler",
      labelButtonRetryItemLoad: "Recommencer",
      labelButtonAbortItemProcessing: "Annuler",
      labelButtonUndoItemProcessing: "Revenir en arrière",
      labelButtonRetryItemProcessing: "Recommencer",
      labelButtonProcessItem: "Transférer",
      labelMaxFileSizeExceeded: "Le fichier est trop volumineux",
      labelMaxFileSize: "La taille maximale de fichier est {filesize}",
      labelMaxTotalFileSizeExceeded: "Taille totale maximale dépassée",
      labelMaxTotalFileSize: "La taille totale maximale des fichiers est {filesize}",
      labelFileTypeNotAllowed: "Fichier non valide",
      fileValidateTypeLabelExpectedTypes: "Attendu {allButLastType} ou {lastType}",
      imageValidateSizeLabelFormatError: "Type d'image non pris en charge",
      imageValidateSizeLabelImageSizeTooSmall: "L'image est trop petite",
      imageValidateSizeLabelImageSizeTooBig: "L'image est trop grande",
      imageValidateSizeLabelExpectedMinSize: "La taille minimale est {minWidth} × {minHeight}",
      imageValidateSizeLabelExpectedMaxSize: "La taille maximale est {maxWidth} × {maxHeight}",
      imageValidateSizeLabelImageResolutionTooLow: "La résolution est trop faible",
      imageValidateSizeLabelImageResolutionTooHigh: "La résolution est trop élevée",
      imageValidateSizeLabelExpectedMinResolution: "La résolution minimale est {minResolution}",
      imageValidateSizeLabelExpectedMaxResolution: "La résolution maximale est {maxResolution}",

      imagePreviewHeight: 170,
      instantUpload: true,
      server: {
        process: {
          url: dataJsonForm.file_upload,
          method: 'POST',
          headers: { 'X-CSRF-TOKEN': '{{ csrf_token("file_upload") }}' },
          onload: txt => JSON.parse(txt).url
        },
        revert: {
          url: dataJsonForm.file_revert,
          method: 'DELETE',
          headers: { 'X-CSRF-TOKEN': '{{ csrf_token("file_revert") }}' },
          onload: r => r
        }
      }
    });

    pond.on('processfilestart', function (file) {
      // console.log('Upload started:', file.filename);
      refreshNavButtons();
    });

    pond.on('processfile', function (error, file) {
      if (!error) {
        // console.log('Upload completed:', file.filename);
        setTimeout(() => {
          refreshNavButtons();
        }, 100);
      }
    });

    pond.on('processfileerror', function (error, file) {
      console.error('Upload failed:', file.filename);
      setTimeout(() => {
        refreshNavButtons();
      }, 100);
    });

    pond.on('processfileabort', function (file) {
      // console.log('Upload aborted:', file.filename);
      setTimeout(() => {
        refreshNavButtons();
      }, 100);
    });

    pond.on('removefile', function (error, file) {
      // console.log('File removed:', file.filename);
      setTimeout(() => {
        refreshNavButtons();
      }, 100);
    });

    // Your existing code continues...
    pond.element.dataset.metaKey = meta['data-name'] || meta.name || pond.id;

    pond.on('init', () => {
      // Wait a tick to ensure FilePond is fully initialized
      setTimeout(() => {
        const hiddenInput = pond.element.querySelector('input[type="file"]');
        if (!hiddenInput) return;

        Object.entries(meta).forEach(([k, v]) => {
          if (v && !['id', 'name', 'class'].includes(k.toLowerCase())) {
            hiddenInput.setAttribute(k, v);
          }
        });
      }, 0);
    });

    const key = meta['data-name'] || meta.name || pond.id;
    window.filePondRegistry.set(key, { pond, meta });
  });

  $('.quantity-wrapper').each(function () {
    const $wrapper = $(this);
    const $input = $wrapper.find('input[type="number"]');
    const step = parseInt($input.attr('step')) || 1;
    const min = parseInt($input.attr('min')) || 0;
    const max = parseInt($input.attr('max')) || 10000;

    $wrapper.find('.quantity-btn--minus').on('click', function () {
      let value = parseInt($input.val()) || 0;
      value = Math.max(min, value - step);
      $input
        .val(value)
        .trigger('change');
    });

    $wrapper.find('.quantity-btn--plus').on('click', function () {
      let value = parseInt($input.val()) || 0;
      value = Math.min(max, value + step);
      $input
        .val(value)
        .trigger('change');
    });

  });

  setupReservationPicker();
});

$(document).on("click", "[data-modal-type='form']", function () {
  var btn = $(this);
  var formId = $(this).data("form-id");       // e.g., 123
  var modalSelector = "#formPopin" + formId;
  var formModal = $(modalSelector);

  // If the modal doesn't exist, create it
  if (formModal.length === 0) {
    // Example of an iframe-based modal
    var modalHtml = `
      <div id="formPopin${formId}" data-form-id="${formId}" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
        <div class="modal-dialog modal-dialog-scrollabl modal-dialog-centered" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"><i class="icon icon--close"></i></button>
            </div>
            <div class="modal-body modal-loader" style="height: 90vh;">
              <!-- Instead of injecting .flexible-form here, we place an iframe -->
              <iframe id="iframeForm${formId}" src="${contactUrlTemplate.replace('ID_PLACEHOLDER', formId)}?formType=modal" width="100%" height="100%" frameborder="0"></iframe>
            </div>
          </div>
        </div>
      </div>`;

    $("body").append(modalHtml);
    formModal = $(modalSelector);

    // Once the iframe is actually loaded, remove the loader class
    $("#iframeForm" + formId).on("load", function () {
      formModal.find(".modal-body").removeClass("modal-loader");
    });

    // Just show the modal
    formModal.modal("show");
  } else {
    // If the modal already exists, just display it again
    formModal.modal("show");
  }
});

$(document).on("click", "#refreshCaptchaBtn", function () {
  var $btn = $(this);
  var cookieName = $btn.data('cookie-name');

  if (window.location.href.indexOf('public') !== -1) {
    var publicIndex = window.location.href.indexOf('public') + 'public'.length;
    var basePath = window.location.href.substring(0, publicIndex);
    var url = basePath + '/contact/refresh/captcha';
  } else {
    var url = '/contact/refresh/captcha';
  }

  $.ajax({
    url: url,    // Adjust as necessary
    method: 'POST',
    dataType: 'json',
    data: { cookieName: cookieName },
    success: function (data) {
      var $image = $btn.closest('.captcha-container').find('.captcha-image');
      $image.attr('src', data.captcha_image_data);
    },
    error: function (xhr, status, error) {
      console.error('Captcha refresh failed:', error);
    }
  });
});