function genform(divId, data) {
  const container = document.getElementById(divId);
  if (!container) {
    console.error(`Div with ID ${divId} not found`);
    return;
  }

  // Store reference to original data (no deep copy)
  container._formData = data;
  const lang = window.lang || "en";

  // Initialize container HTML
  container.innerHTML = `
        <div style="font-family: Arial, sans-serif;">
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <h3 style="font-size: 1.5em;">${getLabel({ label: { en: "Form in", th: "ฟอร์มใน" } }, lang)} ${divId}</h3>
            </div>
            <div id="${divId}-fields"></div>
            <div style="display:none;">
                <textarea id="${divId}-input" placeholder="Enter JSON schema"></textarea>
                <button id="${divId}-copy-btn">Copy to Schema</button>
                <textarea id="${divId}-output" readonly></textarea>
            </div>
        </div>
    `;

  const fieldsDiv = document.getElementById(`${divId}-fields`);
  const schema = container._formData;

  // Organize segments and sections
  const segments = new Map();
  if (schema.grouping) {
    schema.grouping.name.forEach((name, i) => {
      if (schema.grouping.type[i] === "segment") {
        segments.set(name, {
          label: getLabel({ label: schema.grouping.label }, lang)[i] || name,
          sections: new Map(),
        });
      }
    });
  }

  // Map fields to segments and sections
  for (const key in schema) {
    if (key === "grouping") continue;
    const field = schema[key];
    const segment = field.segment?.[0] || schema.grouping?.name[0] || "default";
    if (!segments.has(segment)) {
      segments.set(segment, { label: segment, sections: new Map() });
    }
    if (field.type === "section") {
      segments.get(segment).sections.set(key, getLabel(field, lang) || key);
    } else if (field.section) {
      if (!segments.get(segment).sections.has(field.section)) {
        if (schema[field.section]) {
          segments
            .get(segment)
            .sections.set(
              field.section,
              getLabel({ label: schema[field.section]?.label }, lang) ||
                field.section,
            );
        } else {
          console.warn(
            `Section ${field.section} for field ${key} not found in schema`,
          );
        }
      }
    } else {
      console.warn(`Field ${key} has no section assigned`);
    }
  }

  // Generate form structure
  segments.forEach((segmentData, segmentId) => {
    const segDetails = document.createElement("details");
    segDetails.className = "segment";
    segDetails.style.cssText =
      "border: 2px solid #4a90e2; border-radius: 8px; margin-bottom: 10px; padding: 10px;";
    segDetails.id = `${divId}-segment-${encodeFieldKey(segmentId)}`;
    segDetails.open = true;
    segDetails.innerHTML = `<summary style="font-weight: bold; cursor: pointer;">${getLabel({ label: { en: "Segment", th: "ส่วน" } }, lang)}: ${segmentData.label}</summary>`;

    const segDiv = document.createElement("div");
    segDiv.style.padding = "10px";

    segmentData.sections.forEach((sectionLabel, sectionId) => {
      const secDetails = document.createElement("details");
      secDetails.className = "section";
      secDetails.id = `${divId}-section-${encodeFieldKey(sectionId)}`;
      secDetails.style.cssText =
        "border: 1px solid #888; border-radius: 5px; margin: 8px 0; padding: 8px;";
      secDetails.open = true;

      // Calculate section totals for progress bar
      let sectionTotals = {
        allFields: 0,
        requiredFields: 0,
        answeredFields: 0,
        answeredRequiredFields: 0,
        totalScore: 0,
        totalScoreWeighted: 0,
        maxPossibleScore: 0,
        maxPossibleScoreWeighted: 0,
        totalFiles: 0,
        unansweredFields: [],
      };

      for (const key in schema) {
        if (key === "grouping" || schema[key].type === "section") continue;
        const field = schema[key];
        if (field.section !== sectionId || !field.segment?.includes(segmentId))
          continue;
        if (!field.data_type && !field.type) {
          console.warn(`Field ${key} has no data_type or type defined`);
          continue;
        }

        const currentScore = calculateCurrentScore(field);
        const maxScore = calculateMaxScore(field);
        const isAnswered = isFieldAnswered(field);
        const isFile = field.data_type === "attachment";
        const fileCount = isFile ? countFiles(field) : 0;

        sectionTotals.allFields++;
        if (field.required) sectionTotals.requiredFields++;
        if (isAnswered) sectionTotals.answeredFields++;
        if (field.required && isAnswered)
          sectionTotals.answeredRequiredFields++;
        sectionTotals.totalScore += isAnswered ? field.score || 1 : 0;
        sectionTotals.totalScoreWeighted += currentScore;
        sectionTotals.maxPossibleScore += field.score || 1;
        sectionTotals.maxPossibleScoreWeighted += maxScore;
        sectionTotals.totalFiles += fileCount;
        if (field.required && !isFieldAnswered(field)) {
          if (
            document.getElementById(`${divId}-field-${encodeFieldKey(key)}`)
          ) {
            sectionTotals.unansweredFields.push({
              key,
              label: getLabel(field, lang) || key,
            });
          } else {
            console.warn(
              `Field ${key} not rendered in DOM, skipping from unanswered list`,
            );
          }
        }
      }

      // Section title with progress bar, styled like section-summary
      const progressPercent =
        sectionTotals.requiredFields > 0
          ? Math.round(
              (sectionTotals.answeredRequiredFields /
                sectionTotals.requiredFields) *
                100,
            )
          : 100;
      secDetails.innerHTML = `
        <summary style="cursor: pointer; margin-top: 10px; padding: 8px; background-color: #f0f0f0; border-radius: 4px; font-size: 0.9em;">
          <span style="font-weight: bold;">${sectionLabel}</span>
        </summary>
        <div id="${divId}-section-header-${encodeFieldKey(sectionId)}" style="margin-bottom: 8px; padding: 8px; background-color: #f0f0f0; border-radius: 4px; font-size: 0.9em;">
          <div style="font-weight: bold;">${sectionLabel}</div>
          <div style="margin-top: බ
            5px;">
            [Progress: ${progressPercent}% (${sectionTotals.answeredRequiredFields}/${sectionTotals.requiredFields})]
            <div style="width: 100%; background-color: #e0e0e0; height: 10px; border-radius: 5px; overflow: hidden;">
              <div style="width: ${progressPercent}%; background-color: #4caf50; height: 100%;"></div>
            </div>
          </div>
        </div>
      `;

      const secDiv = document.createElement("div");
      secDiv.style.padding = "8px";

      let hasField = false;
      for (const key in schema) {
        if (key === "grouping" || schema[key].type === "section") continue;
        const field = schema[key];
        if (field.section !== sectionId || !field.segment?.includes(segmentId))
          continue;

        hasField = true;
        const fieldDiv = document.createElement("div");
        fieldDiv.className = "form-field";
        fieldDiv.id = `${divId}-field-${encodeFieldKey(key)}`;
        fieldDiv.style.cssText =
          "background-color: #f9f9f9; padding: 10px; margin-bottom: 10px; border-radius: 4px;";
        if (field.required && !isFieldAnswered(field)) {
          fieldDiv.style.border = "2px solid red";
        }

        const label = document.createElement("label");
        label.style.cssText =
          "font-weight: 300; margin-right: 6px; display: block; padding-bottom: 5px; border-bottom: 1px solid #ddd;";
        if (field.required) label.classList.add("required-field");
        label.textContent =
          (getLabel(field, lang) || key) + (field.required ? " *" : "");
        label.htmlFor = `${divId}-${encodeFieldKey(key)}`;
        if (field.score !== undefined || field.weights) {
          const scoreDisplay = document.createElement("span");
          scoreDisplay.className = "score-display";
          const maxScore = calculateMaxScore(field);
          const currentScore = calculateCurrentScore(field);
          if (typeof window.score !== "undefined" && window.score) {
            scoreDisplay.textContent = `(Score: ${currentScore}/${maxScore})`;
          }
          label.appendChild(scoreDisplay);
        }
        fieldDiv.appendChild(label);

        const input = createInputElement(divId, key, field, lang, schema);
        fieldDiv.appendChild(input);
        fieldDiv.appendChild(
          createResetButton(divId, key, field, input, lang, schema, fieldDiv),
        );

        // Add score bar area
        const scoreBar = document.createElement("div");
        scoreBar.className = "score-bar";
        scoreBar.style.cssText =
          "margin-top: 5px; font-size: 0.9em; color: #555;";
        const currentScore = calculateCurrentScore(field);
        const maxScore = calculateMaxScore(field);
        const weight = field.weights ? field.weights.join(", ") : "1";
        const fileCount =
          field.data_type === "attachment" ? countFiles(field) : 0;
        const value = field.value || "";
        scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
        fieldDiv.appendChild(scoreBar);

        secDiv.appendChild(fieldDiv);
      }

      if (hasField) {
        // Add section summary
        const sectionSummary = document.createElement("details");
        sectionSummary.className = "section-summary";
        sectionSummary.id = `${divId}-summary-${encodeFieldKey(segmentId)}-${encodeFieldKey(sectionId)}`;
        sectionSummary.style.cssText =
          "margin-top: 10px; padding: 8px; background-color: #f0f0f0; border-radius: 4px; font-size: 0.9em;";
        sectionSummary.open = true;
        const unansweredCount =
          sectionTotals.requiredFields - sectionTotals.answeredRequiredFields;
        sectionSummary.innerHTML = `
          <summary style="cursor: pointer;">Unanswered (${unansweredCount}/${sectionTotals.allFields}/${sectionTotals.requiredFields})</summary>
          <div style="padding: 8px;">
            [field total: ${sectionTotals.allFields}, score: ${sectionTotals.totalScore}, achieved score: ${sectionTotals.totalScoreWeighted}, maxscore: ${sectionTotals.maxPossibleScoreWeighted}, total required: ${sectionTotals.requiredFields}, answered required/total: ${sectionTotals.answeredRequiredFields}/${sectionTotals.requiredFields}, unanswered required/total: ${unansweredCount}/${sectionTotals.requiredFields}, Files: ${sectionTotals.totalFiles}]
            ${
              sectionTotals.unansweredFields.length > 0
                ? `
              <div style="margin-top: 10px; color: red;">
                <strong>Unanswered Required Fields:</strong>
                <ul style="margin: 5px 0; padding-left: 20px;">
                  ${sectionTotals.unansweredFields
                    .filter((field) =>
                      document.getElementById(
                        `${divId}-field-${encodeFieldKey(field.key)}`,
                      ),
                    )
                    .map(
                      (field) => `
                      <li style="max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
                        <a href="javascript:scrollToField('${encodeFieldKey(field.key)}', '${divId}')"
                           style="text-decoration: none; color: red;"
                           title="${field.label}">
                          ${field.label}
                        </a>
                      </li>
                    `,
                    )
                    .join("")}
                </ul>
              </div>
            `
                : ""
            }
          </div>
        `;
        secDiv.appendChild(sectionSummary);
        segDiv.appendChild(secDetails);
        secDetails.appendChild(secDiv);
      }
    });

    segDetails.appendChild(segDiv);
    fieldsDiv.appendChild(segDetails);
  });

  // Handle schema copy button
  const copyBtn = document.getElementById(`${divId}-copy-btn`);
  copyBtn.addEventListener("click", () => {
    const inputEl = document.getElementById(`${divId}-input`);
    try {
      const newSchema = JSON.parse(inputEl.value);
      genform(divId, newSchema);
    } catch (e) {
      console.error(`Invalid JSON in ${divId}-input: ${e.message}`);
      alert(
        getLabel(
          {
            label: {
              en: `Invalid JSON: ${e.message}`,
              th: `JSON ไม่ถูกต้อง: ${e.message}`,
            },
          },
          lang,
        ),
      );
    }
  });

  listenform(divId);
}

// Helper function to check if a field is answered
function isFieldAnswered(field) {
  const inputType = field.data_type || field.type;
  if (inputType === "checkbox") {
    return Array.isArray(field.value) && field.value.length > 0;
  } else if (inputType === "radio" || inputType === "select") {
    return field.value !== null && field.value !== "";
  } else if (inputType === "attachment") {
    return field.value && countFiles(field) > 0;
  } else {
    return field.value !== null && field.value !== "";
  }
}

// Helper function to count files
function countFiles(field) {
  if (!field || !field.value) return 0;
  return field.value.split(",").filter((f) => f.trim()).length;
}

// Helper function to create input elements
function createInputElement(divId, key, field, lang, schema) {
  const inputType = field.data_type || field.type;
  let input;

  if (inputType === "textarea") {
    input = document.createElement("textarea");
    input.id = `${divId}-${encodeFieldKey(key)}`;
    input.value = field.value || "";
    input.style.width = "260px";
  } else if (inputType === "radio") {
    input = document.createElement("div");
    input.style.cssText = "display: flex; flex-direction: column; gap: 5px;";
    getOptions(field, lang).forEach((opt, idx) => {
      const radioLabel = document.createElement("label");
      radioLabel.style.cssText =
        "margin-right: 8px; display: flex; align-items: center;";
      const val = idx;
      radioLabel.innerHTML = `<input type="radio" name="${divId}-${encodeFieldKey(key)}" value="${val}" ${field.value === val ? "checked" : ""}> ${opt}`;
      input.appendChild(radioLabel);
    });
  } else if (inputType === "checkbox") {
    input = document.createElement("div");
    input.style.cssText = "display: flex; flex-direction: column; gap: 5px;";
    getOptions(field, lang).forEach((opt, idx) => {
      const checkLabel = document.createElement("label");
      checkLabel.style.cssText =
        "margin-right: 8px; display: flex; align-items: center;";
      const val = idx;
      checkLabel.innerHTML = `<input type="checkbox" name="${divId}-${encodeFieldKey(key)}[]" value="${val}" ${field.value && field.value.includes(val) ? "checked" : ""}> ${opt}`;
      input.appendChild(checkLabel);
    });
  } else if (inputType === "select") {
    input = document.createElement("select");
    input.id = `${divId}-${encodeFieldKey(key)}`;
    input.style.width = "260px";
    getOptions(field, lang).forEach((opt, idx) => {
      const option = document.createElement("option");
      const value = idx === 0 ? "" : opt;
      option.value = value;
      option.textContent = opt;
      option.selected = field.value === value;
      input.appendChild(option);
    });
  } else if (inputType === "attachment") {
    input = document.createElement("div");
    const textInput = document.createElement("input");
    textInput.type = "text";
    textInput.id = `${divId}-${encodeFieldKey(key)}`;
    textInput.value = field.value || "";
    textInput.placeholder = getLabel(
      {
        label: {
          en: "Enter file names (comma-separated)",
          th: "ป้อนชื่อไฟล์ (คั่นด้วยเครื่องหมายจุลภาค)",
        },
      },
      lang,
    );
    textInput.style.width = "260px";
    input.appendChild(textInput);
    const fileCount = document.createElement("div");
    fileCount.id = `${divId}-filecount-${encodeFieldKey(key)}`;
    fileCount.style.marginTop = "5px";
    fileCount.textContent = `Files: ${countFiles(field)}`;
    input.appendChild(fileCount);
    const buttonDiv = document.createElement("div");
    buttonDiv.style.marginTop = "5px";
    const addFileBtn = document.createElement("button");
    addFileBtn.textContent = getLabel(
      { label: { en: "Add file", th: "เพิ่มไฟล์" } },
      lang,
    );
    addFileBtn.style.cssText =
      "margin-left: 10px; padding: 4px 8px; cursor: pointer;";
    addFileBtn.onclick = () => {
      toggleUploadPanel();
      updateFileListFromInput(`${divId}-${encodeFieldKey(key)}`);
      const count = countFiles(schema[key]);
      fileCount.textContent = `Files: ${count}`;
      schema[key].value = document.getElementById(
        `${divId}-${encodeFieldKey(key)}`,
      ).value;
      const fieldDiv = document.getElementById(
        `${divId}-field-${encodeFieldKey(key)}`,
      );
      if (fieldDiv) {
        fieldDiv.style.border =
          field.required && !isFieldAnswered(field) ? "2px solid red" : "";
      }
      const scoreBar = fieldDiv?.querySelector(".score-bar");
      const currentScore = calculateCurrentScore(field);
      const maxScore = calculateMaxScore(field);
      const weight = field.weights ? field.weights.join(", ") : "1";
      const fileCountVal = countFiles(field);
      const value = field.value || "";
      if (scoreBar) {
        scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCountVal}, value: ${value}]`;
      }
      if (document.getElementById("jumperhelper")) {
        const summary = QSummary(schema).summary;
        updateJumperHelperWithUnanswered(summary, schema);
      }
      updateSectionSummaries(divId, schema, lang);
    };
    buttonDiv.appendChild(addFileBtn);
    const countFilesBtn = document.createElement("button");
    countFilesBtn.textContent = getLabel(
      { label: { en: "Count Files", th: "นับไฟล์" } },
      lang,
    );
    countFilesBtn.style.cssText =
      "margin-left: 10px; padding: 4px 8px; cursor: pointer;";
    countFilesBtn.onclick = () => {
      schema[key].value = document.getElementById(
        `${divId}-${encodeFieldKey(key)}`,
      ).value;
      fileCount.textContent = `Files: ${countFiles(schema[key])}`;
      const fieldDiv = document.getElementById(
        `${divId}-field-${encodeFieldKey(key)}`,
      );
      if (fieldDiv) {
        fieldDiv.style.border =
          field.required && !isFieldAnswered(field) ? "2px solid red" : "";
      }
      const scoreBar = fieldDiv?.querySelector(".score-bar");
      const currentScore = calculateCurrentScore(field);
      const maxScore = calculateMaxScore(field);
      const weight = field.weights ? field.weights.join(", ") : "1";
      const fileCountVal = countFiles(field);
      const value = field.value || "";
      if (scoreBar) {
        scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCountVal}, value: ${value}]`;
      }
      if (document.getElementById("jumperhelper")) {
        const summary = QSummary(schema).summary;
        updateJumperHelperWithUnanswered(summary, schema);
      }
      updateSectionSummaries(divId, schema, lang);
    };
    buttonDiv.appendChild(countFilesBtn);
    input.appendChild(buttonDiv);
  } else {
    input = document.createElement("input");
    input.id = `${divId}-${encodeFieldKey(key)}`;
    input.type = inputType === "string" ? "text" : inputType || "text";
    input.value = field.value || (inputType === "number" ? 0 : "");
    input.style.width = "260px";
  }

  return input;
}

// Helper function to create reset button
function createResetButton(divId, key, field, input, lang, schema, fieldDiv) {
  const inputType = field.data_type || field.type;
  const resetBtn = document.createElement("button");
  resetBtn.textContent = getLabel(
    { label: { en: "Reset", th: "รีเซ็ต" } },
    lang,
  );
  resetBtn.style.cssText =
    "margin-left: 10px; padding: 4px 8px; cursor: pointer;";
  resetBtn.onclick = () => {
    if (inputType === "radio") {
      schema[key].value = null;
      document
        .querySelectorAll(`input[name="${divId}-${encodeFieldKey(key)}"]`)
        .forEach((el) => {
          el.checked = false;
          fieldDiv.style.border = field.required ? "2px solid red" : "";
        });
    } else if (inputType === "checkbox") {
      schema[key].value = [];
      document
        .querySelectorAll(`input[name="${divId}-${encodeFieldKey(key)}[]"]`)
        .forEach((el) => {
          el.checked = false;
          fieldDiv.style.border = field.required ? "2px solid red" : "";
        });
    } else if (inputType === "select") {
      schema[key].value = "";
      const inputEl = document.getElementById(
        `${divId}-${encodeFieldKey(key)}`,
      );
      inputEl.value = "";
      fieldDiv.style.border = field.required ? "2px solid red" : "";
    } else if (inputType === "attachment") {
      schema[key].value = "";
      const textInput = document.getElementById(
        `${divId}-${encodeFieldKey(key)}`,
      );
      textInput.value = "";
      fieldDiv.style.border = field.required ? "2px solid red" : "";
      document.getElementById(
        `${divId}-filecount-${encodeFieldKey(key)}`,
      ).textContent = `Files: 0`;
    } else {
      schema[key].value = inputType === "number" ? 0 : "";
      const inputEl = document.getElementById(
        `${divId}-${encodeFieldKey(key)}`,
      );
      inputEl.value = inputType === "number" ? 0 : "";
      fieldDiv.style.border = field.required ? "2px solid red" : "";
    }
    // Update score bar
    const scoreBar = fieldDiv.querySelector(".score-bar");
    const currentScore = calculateCurrentScore(field);
    const maxScore = calculateMaxScore(field);
    const weight = field.weights ? field.weights.join(", ") : "1";
    const fileCount = field.data_type === "attachment" ? countFiles(field) : 0;
    const value = field.value || "";
    scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
    // Update jumper helper and section summaries
    if (document.getElementById("jumperhelper")) {
      const summary = QSummary(schema).summary;
      updateJumperHelperWithUnanswered(summary, schema);
    }
    updateSectionSummaries(divId, schema, lang);
  };
  return resetBtn;
}

// Form input event listener
function listenform(divId) {
  const schema = document.getElementById(divId)._formData;
  const lang = window.lang || "en";

  for (const key in schema) {
    if (key === "grouping" || schema[key].type === "section") continue;
    const field = schema[key];
    const inputType = field.data_type || field.type;
    const inputId = `${divId}-${encodeFieldKey(key)}`;
    const fieldDiv = document.getElementById(
      `${divId}-field-${encodeFieldKey(key)}`,
    );

    if (["string", "textarea", "text", "number"].includes(inputType)) {
      const inputEl = document.getElementById(inputId);
      if (inputEl) {
        inputEl.addEventListener("input", () => {
          schema[key].value =
            inputType === "number"
              ? parseFloat(inputEl.value) || 0
              : inputEl.value.trim();
          fieldDiv.style.border =
            field.required && !isFieldAnswered(field) ? "2px solid red" : "";
          // Update score bar
          const scoreBar = fieldDiv.querySelector(".score-bar");
          const currentScore = calculateCurrentScore(field);
          const maxScore = calculateMaxScore(field);
          const weight = field.weights ? field.weights.join(", ") : "1";
          const fileCount =
            field.data_type === "attachment" ? countFiles(field) : 0;
          const value = field.value || "";
          scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
          // Update jumper helper and section summaries
          if (document.getElementById("jumperhelper")) {
            const summary = QSummary(schema).summary;
            updateJumperHelperWithUnanswered(summary, schema);
          }
          updateSectionSummaries(divId, schema, lang);
        });
      }
    } else if (inputType === "radio") {
      document.querySelectorAll(`input[name="${inputId}"]`).forEach((radio) => {
        radio.addEventListener("change", () => {
          schema[key].value = parseInt(radio.value);
          fieldDiv.style.border =
            field.required && !isFieldAnswered(field) ? "2px solid red" : "";
          // Update score bar
          const scoreBar = fieldDiv.querySelector(".score-bar");
          const currentScore = calculateCurrentScore(field);
          const maxScore = calculateMaxScore(field);
          const weight = field.weights ? field.weights.join(", ") : "1";
          const fileCount =
            field.data_type === "attachment" ? countFiles(field) : 0;
          const value = field.value || "";
          scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
          // Update jumper helper and section summaries
          if (document.getElementById("jumperhelper")) {
            const summary = QSummary(schema).summary;
            updateJumperHelperWithUnanswered(summary, schema);
          }
          updateSectionSummaries(divId, schema, lang);
        });
      });
    } else if (inputType === "checkbox") {
      document
        .querySelectorAll(`input[name="${inputId}[]"]`)
        .forEach((checkbox) => {
          checkbox.addEventListener("change", () => {
            const checked = Array.from(
              document.querySelectorAll(`input[name="${inputId}[]"]:checked`),
            ).map((el) => parseInt(el.value));
            schema[key].value = checked;
            fieldDiv.style.border =
              field.required && !isFieldAnswered(field) ? "2px solid red" : "";
            // Update score bar
            const scoreBar = fieldDiv.querySelector(".score-bar");
            const currentScore = calculateCurrentScore(field);
            const maxScore = calculateMaxScore(field);
            const weight = field.weights ? field.weights.join(", ") : "1";
            const fileCount =
              field.data_type === "attachment" ? countFiles(field) : 0;
            const value = field.value || "";
            scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
            // Update jumper helper and section summaries
            if (document.getElementById("jumperhelper")) {
              const summary = QSummary(schema).summary;
              updateJumperHelperWithUnanswered(summary, schema);
            }
            updateSectionSummaries(divId, schema, lang);
          });
        });
    } else if (inputType === "select") {
      const inputEl = document.getElementById(inputId);
      if (inputEl) {
        inputEl.addEventListener("change", () => {
          schema[key].value = inputEl.value;
          fieldDiv.style.border =
            field.required && !isFieldAnswered(field) ? "2px solid red" : "";
          // Update score bar
          const scoreBar = fieldDiv.querySelector(".score-bar");
          const currentScore = calculateCurrentScore(field);
          const maxScore = calculateMaxScore(field);
          const weight = field.weights ? field.weights.join(", ") : "1";
          const fileCount =
            field.data_type === "attachment" ? countFiles(field) : 0;
          const value = field.value || "";
          scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCount}, value: ${value}]`;
          // Update jumper helper and section summaries
          if (document.getElementById("jumperhelper")) {
            const summary = QSummary(schema).summary;
            updateJumperHelperWithUnanswered(summary, schema);
          }
          updateSectionSummaries(divId, schema, lang);
        });
      }
    } else if (inputType === "attachment") {
      const inputEl = document.getElementById(inputId);
      if (inputEl) {
        inputEl.addEventListener("input", () => {
          schema[key].value = inputEl.value;
          const fileCount = document.getElementById(
            `${divId}-filecount-${encodeFieldKey(key)}`,
          );
          fileCount.textContent = `Files: ${countFiles(schema[key])}`;
          const fieldDiv = document.getElementById(
            `${divId}-field-${encodeFieldKey(key)}`,
          );
          if (fieldDiv) {
            fieldDiv.style.border =
              field.required && !isFieldAnswered(field) ? "2px solid red" : "";
          }
          const scoreBar = fieldDiv?.querySelector(".score-bar");
          const currentScore = calculateCurrentScore(field);
          const maxScore = calculateMaxScore(field);
          const weight = field.weights ? field.weights.join(", ") : "1";
          const fileCountVal = countFiles(field);
          const value = field.value || "";
          if (scoreBar) {
            scoreBar.textContent = `[score: ${currentScore}, weight: ${weight}, maxscore: ${maxScore}, required: ${field.required ? "yes" : "no"}, Files: ${fileCountVal}, value: ${value}]`;
          }
          if (document.getElementById("jumperhelper")) {
            const summary = QSummary(schema).summary;
            updateJumperHelperWithUnanswered(summary, schema);
          }
          updateSectionSummaries(divId, schema, lang);
        });
      }
    }
  }

  // Initial update of jumper helper and section summaries
  if (document.getElementById("jumperhelper")) {
    const summary = QSummary(schema).summary;
    updateJumperHelperWithUnanswered(summary, schema);
  }
  updateSectionSummaries(divId, schema, lang);
}

// Helper function to update section summaries
function updateSectionSummaries(divId, schema, lang) {
  const segments = new Map();
  if (schema.grouping) {
    schema.grouping.name.forEach((name, i) => {
      if (schema.grouping.type[i] === "segment") {
        segments.set(name, {
          label: getLabel({ label: schema.grouping.label }, lang)[i] || name,
          sections: new Map(),
        });
      }
    });
  }

  for (const key in schema) {
    if (key === "grouping") continue;
    const field = schema[key];
    const segment = field.segment?.[0] || schema.grouping?.name[0] || "default";
    if (!segments.has(segment)) {
      segments.set(segment, { label: segment, sections: new Map() });
    }
    if (field.type === "section") {
      segments.get(segment).sections.set(key, getLabel(field, lang) || key);
    } else if (field.section) {
      if (!segments.get(segment).sections.has(field.section)) {
        if (schema[field.section]) {
          segments
            .get(segment)
            .sections.set(
              field.section,
              getLabel({ label: schema[field.section]?.label }, lang) ||
                field.section,
            );
        } else {
          console.warn(
            `Section ${field.section} for field ${key} not found in schema`,
          );
        }
      }
    } else {
      console.warn(`Field ${key} has no section assigned`);
    }
  }

  segments.forEach((segmentData, segmentId) => {
    segmentData.sections.forEach((sectionLabel, sectionId) => {
      let sectionTotals = {
        allFields: 0,
        requiredFields: 0,
        answeredFields: 0,
        answeredRequiredFields: 0,
        totalScore: 0,
        totalScoreWeighted: 0,
        maxPossibleScore: 0,
        maxPossibleScoreWeighted: 0,
        totalFiles: 0,
        unansweredFields: [],
      };

      for (const key in schema) {
        if (key === "grouping" || schema[key].type === "section") continue;
        const field = schema[key];
        if (field.section !== sectionId || !field.segment?.includes(segmentId))
          continue;
        if (!field.data_type && !field.type) {
          console.warn(`Field ${key} has no data_type or type defined`);
          continue;
        }

        const currentScore = calculateCurrentScore(field);
        const maxScore = calculateMaxScore(field);
        const isAnswered = isFieldAnswered(field);
        const isFile = field.data_type === "attachment";
        const fileCount = isFile ? countFiles(field) : 0;

        sectionTotals.allFields++;
        if (field.required) sectionTotals.requiredFields++;
        if (isAnswered) sectionTotals.answeredFields++;
        if (field.required && isAnswered)
          sectionTotals.answeredRequiredFields++;
        sectionTotals.totalScore += isAnswered ? field.score || 1 : 0;
        sectionTotals.totalScoreWeighted += currentScore;
        sectionTotals.maxPossibleScore += field.score || 1;
        sectionTotals.maxPossibleScoreWeighted += maxScore;
        sectionTotals.totalFiles += fileCount;
        if (field.required && !isFieldAnswered(field)) {
          if (
            document.getElementById(`${divId}-field-${encodeFieldKey(key)}`)
          ) {
            sectionTotals.unansweredFields.push({
              key,
              label: getLabel(field, lang) || key,
            });
          } else {
            console.warn(
              `Field ${key} not rendered in DOM, skipping from unanswered list`,
            );
          }
        }
      }

      const sectionSummary = document.getElementById(
        `${divId}-summary-${encodeFieldKey(segmentId)}-${encodeFieldKey(sectionId)}`,
      );
      if (sectionSummary) {
        const unansweredCount =
          sectionTotals.requiredFields - sectionTotals.answeredRequiredFields;
        sectionSummary.innerHTML = `
          <summary style="cursor: pointer;">Unanswered (${unansweredCount}/${sectionTotals.allFields}/${sectionTotals.requiredFields})</summary>
          <div style="padding: 8px;">
            [field total: ${sectionTotals.allFields}, score: ${sectionTotals.totalScore}, achieved score: ${sectionTotals.totalScoreWeighted}, maxscore: ${sectionTotals.maxPossibleScoreWeighted}, total required: ${sectionTotals.requiredFields}, answered required/total: ${sectionTotals.answeredRequiredFields}/${sectionTotals.requiredFields}, unanswered required/total: ${unansweredCount}/${sectionTotals.requiredFields}, Files: ${sectionTotals.totalFiles}]
            ${
              sectionTotals.unansweredFields.length > 0
                ? `
              <div style="margin-top: 10px; color: red;">
                <strong>Unanswered Required Fields:</strong>
                <ul style="margin: 5px 0; padding-left: 20px;">
                  ${sectionTotals.unansweredFields
                    .map(
                      (field) => `
                    <li style="max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
                      <a href="javascript:scrollToField('${encodeFieldKey(field.key)}', '${divId}')"
                         style="text-decoration: none; color: red;"
                         title="${field.label}">
                        ${field.label}
                      </a>
                    </li>
                  `,
                    )
                    .join("")}
                </ul>
              </div>
            `
                : ""
            }
          </div>
        `;
      }

      // Update section header progress bar
      const sectionHeader = document.getElementById(
        `${divId}-section-header-${encodeFieldKey(sectionId)}`,
      );
      if (sectionHeader) {
        const progressPercent =
          sectionTotals.requiredFields > 0
            ? Math.round(
                (sectionTotals.answeredRequiredFields /
                  sectionTotals.requiredFields) *
                  100,
              )
            : 100;
        sectionHeader.innerHTML = `
          <div style="font-weight: bold;">${sectionLabel}</div>
          <div style="margin-top: 5px;">
            [Progress: ${progressPercent}% (${sectionTotals.answeredRequiredFields}/${sectionTotals.requiredFields})]
            <div style="width: 100%; background-color: #e0e0e0; height: 10px; border-radius: 5px; overflow: hidden;">
              <div style="width: ${progressPercent}%; background-color: #4caf50; height: 100%;"></div>
            </div>
          </div>
        `;
      }
    });
  });
}

// Jumper helper function
function updateJumperHelperWithUnanswered(summary, data) {
  const lang = window.lang || "en";
  const unansweredFields = getUnansweredRequiredFields(data);
  let html =
    "<h3>Quick Navigation</h3><div style='display: flex; flex-wrap: wrap; gap: 10px;'>";

  Object.entries(summary.segments).forEach(([segmentKey, segment]) => {
    const segmentEncoded = encodeFieldKey(segmentKey);
    const segmentTotals = segment.totals;

    html += `<div style='border: 1px solid #ccc; padding: 10px; border-radius: 5px; min-width: 200px;'>
            <h4 style='margin: 0 0 5px 0;'>
                <a href="javascript:scrollToField('${segmentEncoded}', 'genform')" style='text-decoration: none; color: #333;'>
                    ${segment.label}
                </a>
            </h4>
            <div>Fields: ${segmentTotals.answeredFields}/${segmentTotals.allFields}</div>
            <div>Required: ${segmentTotals.answeredRequiredFields}/${segmentTotals.requiredFields}</div>
            <div>Score: ${segmentTotals.totalScoreWeighted}/${segmentTotals.maxPossibleScoreWeighted}</div>
            <div>Files: ${segmentTotals.totalFiles}</div>
            <div style='margin-top: 5px; font-size: 0.9em;'>`;

    Object.entries(segment.sections).forEach(([sectionKey, section]) => {
      const sectionEncoded = encodeFieldKey(sectionKey);
      const sectionTotals = section.totals;

      html += `<div style='margin-bottom: 3px;'>
                <a href="javascript:scrollToField('${sectionEncoded}', 'genform')" style='text-decoration: none; color: #666;'>
                    ${section.label} (${sectionTotals.answeredFields}/${sectionTotals.allFields})
                </a>
            </div>`;
    });

    const segmentUnanswered = unansweredFields
      .filter((field) => field.segment === segmentKey)
      .filter((field) =>
        document.getElementById(`genform-field-${encodeFieldKey(field.key)}`),
      );
    if (segmentUnanswered.length > 0) {
      html += `<div style='margin-top: 10px; color: red;'>
                <strong>Unanswered Required Fields:</strong><ul style='margin: 5px 0; padding-left: 20px;'>`;
      segmentUnanswered.forEach((field) => {
        const sectionLabel = data[field.section]?.label[lang] || field.section;
        html += `<li style='max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;'>
                    <a href="javascript:scrollToField('${encodeFieldKey(field.key)}', 'genform')"
                       style='text-decoration: none; color: red;'
                       title='${field.label} (Section: ${sectionLabel})'>
                        ${field.label} (Section: ${sectionLabel})
                    </a>
                </li>`;
      });
      html += `</ul></div>`;
    }

    html += `</div></div>`;
  });

  html += `</div>`;

  const jumperDiv = document.getElementById("jumperhelper");
  if (jumperDiv) {
    jumperDiv.innerHTML = html;
  } else {
    console.log("Jumperhelper div not found, jumper HTML:", html);
  }

  return html;
}

// Summary calculation function
function QSummary(data) {
  if (!data || !data.grouping || !data.grouping.name) {
    console.warn("Invalid data format: grouping is missing");
    return { segments: [] };
  }

  const result = { segments: [] };
  const summary = {
    segments: {},
    totals: {
      allFields: 0,
      requiredFields: 0,
      answeredFields: 0,
      answeredRequiredFields: 0,
      totalScore: 0,
      totalScoreWeighted: 0,
      maxPossibleScore: 0,
      maxPossibleScoreWeighted: 0,
      totalFiles: 0,
    },
  };

  const segmentMap = {};

  Object.entries(data).forEach(([key, item]) => {
    if (item.type === "field") {
      const segment = item.segment?.[0];
      const section = item.section;
      if (!segment || !section || !data[section]) {
        console.warn(
          `Invalid field ${key}: missing segment or section, or section not found in schema`,
        );
        return;
      }

      if (!summary.segments[segment]) {
        const segmentIndex = data.grouping.name.indexOf(segment);
        summary.segments[segment] = {
          label: data.grouping.label.en[segmentIndex] || segment,
          sections: {},
          totals: {
            allFields: 0,
            requiredFields: 0,
            answeredFields: 0,
            answeredRequiredFields: 0,
            totalScore: 0,
            totalScoreWeighted: 0,
            maxPossibleScore: 0,
            maxPossibleScoreWeighted: 0,
            totalFiles: 0,
          },
        };
      }
      if (!summary.segments[segment].sections[section]) {
        summary.segments[segment].sections[section] = {
          label: data[section]?.label?.en || section,
          totals: {
            allFields: 0,
            requiredFields: 0,
            answeredFields: 0,
            answeredRequiredFields: 0,
            totalScore: 0,
            totalScoreWeighted: 0,
            maxPossibleScore: 0,
            maxPossibleScoreWeighted: 0,
            totalFiles: 0,
          },
        };
      }

      const currentScore = calculateCurrentScore(item);
      const maxScore = calculateMaxScore(item);
      const isAnswered = isFieldAnswered(item);
      const isFile = item.data_type === "attachment";
      const fileCount = isFile ? countFiles(item) : 0;

      const baseScore = isAnswered ? item.score || 1 : 0;
      const baseMaxScore = item.score || 1;

      const sectionTotals = summary.segments[segment].sections[section].totals;
      const segmentTotals = summary.segments[segment].totals;
      const globalTotals = summary.totals;

      sectionTotals.allFields++;
      if (item.required) sectionTotals.requiredFields++;
      if (isAnswered) sectionTotals.answeredFields++;
      if (item.required && isAnswered) sectionTotals.answeredRequiredFields++;
      sectionTotals.totalScore += baseScore;
      sectionTotals.totalScoreWeighted += currentScore;
      sectionTotals.maxPossibleScore += baseMaxScore;
      sectionTotals.maxPossibleScoreWeighted += maxScore;
      sectionTotals.totalFiles += fileCount;

      segmentTotals.allFields++;
      if (item.required) segmentTotals.requiredFields++;
      if (isAnswered) segmentTotals.answeredFields++;
      if (item.required && isAnswered) segmentTotals.answeredRequiredFields++;
      segmentTotals.totalScore += baseScore;
      segmentTotals.totalScoreWeighted += currentScore;
      segmentTotals.maxPossibleScore += baseMaxScore;
      segmentTotals.maxPossibleScoreWeighted += maxScore;
      segmentTotals.totalFiles += fileCount;

      globalTotals.allFields++;
      if (item.required) globalTotals.requiredFields++;
      if (isAnswered) globalTotals.answeredFields++;
      if (item.required && isAnswered) globalTotals.answeredRequiredFields++;
      globalTotals.totalScore += baseScore;
      globalTotals.totalScoreWeighted += currentScore;
      globalTotals.maxPossibleScore += baseMaxScore;
      globalTotals.maxPossibleScoreWeighted += maxScore;
      globalTotals.totalFiles += fileCount;

      if (!segmentMap[segment]) {
        const segmentLabel =
          data.grouping.label?.[data.grouping.name.indexOf(segment)] || segment;
        const segmentObj = {
          id: segment,
          label: segmentLabel,
          sections: [],
        };
        result.segments.push(segmentObj);
        segmentMap[segment] = segmentObj;
      }

      const segmentObj = segmentMap[segment];

      let sectionObj = segmentObj.sections.find((sec) => sec.id === section);
      if (!sectionObj) {
        sectionObj = {
          id: section,
          label: data[section]?.label?.en || section,
          fields: [],
        };
        segmentObj.sections.push(sectionObj);
      }

      sectionObj.fields.push({ key, ...item });
    }
  });

  console.log(`${JSON.stringify(result, null, 2)}`);
  return { result, summary };
}

// Summary rendering function
function customRenderSummary(summary) {
  const output = [];
  output.push(`Total Fields: ${summary.totals.allFields}`);
  output.push(
    `Answered Fields: ${summary.totals.answeredFields}/${summary.totals.allFields}`,
  );
  output.push(
    `Required Fields Answered: ${summary.totals.answeredRequiredFields}/${summary.totals.requiredFields}`,
  );
  output.push(`Total Files: ${summary.totals.totalFiles}`);
  output.push(
    `Total Score (Weighted): ${summary.totals.totalScoreWeighted}/${summary.totals.maxPossibleScoreWeighted}`,
  );
  Object.entries(summary.segments).forEach(([segKey, segment]) => {
    output.push(`Segment: ${segment.label}`);
    output.push(`  Total Fields: ${segment.totals.allFields}`);
    output.push(
      `  Answered Fields: ${segment.totals.answeredFields}/${segment.totals.allFields}`,
    );
    output.push(
      `  Required Fields: ${segment.totals.answeredRequiredFields}/${segment.totals.requiredFields}`,
    );
    output.push(`  Total Files: ${segment.totals.totalFiles}`);
    output.push(
      `  Score: ${segment.totals.totalScoreWeighted}/${segment.totals.maxPossibleScoreWeighted}`,
    );
    Object.entries(segment.sections).forEach(([secKey, section]) => {
      output.push(`  Section: ${section.label}`);
      output.push(
        `    Fields: ${section.totals.answeredFields}/${section.totals.allFields}`,
      );
    });
  });
  return output.join("\n");
}
