import { processTemplateFormTable } from "./templateFormTable.js";
import { processTemplateFormTableData } from "./templateFormTableData.js";
import { processTemplateFormHidden } from "./templateFormHidden.js";
import { some, includes, cloneDeep } from "lodash-es";
import { migrateInputAttributes, migrateTemplateString } from "./templateMigrate.js";
import { getDocumentTemplateInputTypeEntry } from "./templateInputTypes.js";
export const validationRulesRegex = /^(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|requireNotEmpty(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\))(,(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|requireNotEmpty(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\)))*$/;
export function useDocumentTemplate(items, parentTemplates) {
  if (!items) return "";
  if (typeof items === "string") {
    try {
      items = JSON.parse(items);
    } catch (_) {
      return items;
    }
  }
  if (!Array.isArray(items) || !items.every((item) => typeof item === "object" && item !== null)) {
    return "";
  }
  const templateString = items.map((item) => columnWrapTemplateItemString(item, parentTemplates || [])).join("");
  const wrapped = !parentTemplates || parentTemplates.length == 0 ? `<v-container fluid><v-row density='compact'>${templateString}</v-row></v-container>` : `<v-row density='compact'>${templateString}</v-row>`;
  return migrateTemplateString(wrapped);
}
export function templateItemToString(inputItem, parentTemplates, dataVariable = "data") {
  let item = cloneDeep(inputItem);
  item.inputAttributes = migrateInputAttributes(item.inputAttributes?.trim() || "", item.inputType);
  let optionString = "";
  if (item.inputOptions) {
    if (item.inputType === "MasterAutocomplete") {
      optionString += `groupKey="${item.inputOptions}" `;
    }
    if (["VSelect", "VAutocomplete", "VCombobox"].includes(item.inputType)) {
      const choice = optionStringToChoiceObject(item.inputOptions);
      optionString = `item-value="value" item-title="label" :items='${escapeObjectForInlineBinding(choice)}' `;
    }
    if (["FormCheckboxGroup"].includes(item.inputType)) {
      const choice = optionStringToChoiceObject(item.inputOptions);
      optionString = ` :items='${escapeObjectForInlineBinding(choice)}'`;
    }
    if (["VRadio", "VRadioInline"].includes(item.inputType)) {
      const choice = optionStringToChoiceObject(item.inputOptions);
      optionString = choice.map((choiceItem) => `<v-radio label="${choiceItem.label || ""}" value="${choiceItem.value || ""}" ${item.inputAttributes ? " " + item.inputAttributes : ""}></v-radio>`).join("");
    }
    if (item.inputType === "Header") {
      if (typeof item.inputOptions === "string") optionString = item.inputOptions.split(",").join(" ");
    }
  }
  if (item.conditionalDisplay) {
    item.inputAttributes = `${item.inputAttributes?.trim() || ""} v-if="${item.conditionalDisplay}"`.trim();
  }
  if (item.inputType === "FormDateTime" && !item.inputAttributes?.includes("density")) {
    item.inputAttributes = `${item.inputAttributes?.trim() || ""} density="compact"`.trim();
  }
  let templateString;
  const validationRules = item.validationRules ? buildValidationRules(item.validationRules) || "" : "";
  const registryEntry = getDocumentTemplateInputTypeEntry(item.inputType);
  if (registryEntry && typeof registryEntry.render === "function") {
    templateString = registryEntry.render(item, parentTemplates, dataVariable);
    if (item.computedValue && item.variableName) {
      templateString = `${templateString || ""}<FormHidden v-model="${dataVariable}.${item.variableName}" :item-value="data" :hook="()=>${item.computedValue}"/>`.trim();
    }
    return templateString || "";
  }
  switch (item.inputType) {
    case "CustomCode":
      templateString = item.inputCustomCode || "";
      break;
    case "VRadio":
      templateString = `${item.inputLabel ? `<p class="opacity-60">${item.inputLabel}</p>` : ""} <v-radio-group ${item.inputAttributes?.trim()} v-model="${dataVariable}.${item.variableName || ""}"${validationRules ? " " + validationRules.trim() : ""}>${optionString ? " " + optionString.trim() : ""}</v-radio-group>`;
      break;
    case "VRadioInline":
      templateString = `<v-radio-group ${item.inputAttributes?.trim()} v-model="${dataVariable}.${item.variableName || ""}" inline ${validationRules ? " " + validationRules.trim() : ""}>${item.inputLabel ? `<template #prepend><span class="opacity-60">${item.inputLabel}</span></template>` : ""}${optionString ? " " + optionString.trim() : ""}</v-radio-group>`;
      break;
    case "Separator":
      templateString = `</v-row><v-row density='compact'${item.customClass ? ` class="${item.customClass}"` : ""}${item.customStyle ? ` class="${item.customStyle}"` : ""}>`;
      break;
    case "Header":
      templateString = `<div class="${optionString || "text-h4 font-weight-medium"}">${item.inputLabel || item.variableName || ""}</div>`;
      break;
    case "FormTable":
      templateString = processTemplateFormTable(item, parentTemplates, dataVariable);
      break;
    case "FormTableData":
      templateString = processTemplateFormTableData(item, parentTemplates, dataVariable);
      break;
    case "FormHidden":
      templateString = processTemplateFormHidden(item, parentTemplates);
      break;
    case "DocumentForm":
      const parentTemplatesString = typeof parentTemplates === "string" ? parentTemplates : parentTemplates.join("|");
      templateString = `<document-form :model-value="data" templateCode="${item.inputOptions || ""}" parent-templates="${parentTemplatesString}"></document-form>`;
      break;
    default:
      templateString = processDefaultTemplate(item, void 0, optionString, void 0, dataVariable);
  }
  if (item.computedValue && item.variableName) {
    templateString = `${templateString || ""}<FormHidden v-model="${dataVariable}.${item.variableName}" :item-value="data" :hook="()=>${item.computedValue}"/>`.trim();
  }
  return templateString || "";
}
function columnWrapTemplateItemString(item, parentTemplates, dataVariable = "data") {
  let templateString = templateItemToString(item, parentTemplates, dataVariable);
  if (!["Separator", "FormHidden"].includes(item.inputType)) templateString = `<v-col${item.width ? ` cols="${item.width}"` : ""}${item.columnAttributes ? " " + item.columnAttributes : ""} :class="(injectedClass) ? injectedClass['${item.variableName || ""}'] : undefined"${item.customClass ? ` class="${item.customClass}"` : ""}${item.customStyle ? ` class="${item.customStyle}"` : ""}>${templateString}</v-col>`;
  if (["Header", "DocumentForm"].includes(item.inputType)) templateString = `</v-row><v-row density='compact' ${item.customClass ? ` class="${item.customClass}"` : ""}${item.customStyle ? ` class="${item.customStyle}"` : ""}>${templateString}</v-row><v-row density='compact'>`;
  return templateString || "";
}
export function optionStringToChoiceObject(option) {
  if (typeof option === "string") {
    if (!/^[^'",]+(,[^'",]+)*$/.test(option.trim())) return [];
    return option.split(",").map((item) => {
      item = item.trim();
      if (item.includes("|")) {
        const [label, value] = item.split("|").map((str) => str.trim().replace(/^['"]|['"]$/g, ""));
        return { label: label || "", value: value || "" };
      }
      item = item.replace(/^['"]|['"]$/g, "");
      return { label: item, value: item };
    });
  }
  if (Array.isArray(option) && option.every((item) => typeof item === "object" && item !== null)) {
    return option.sort((a, b) => (a.id ?? Infinity) - (b.id ?? Infinity)).map((item) => ({
      label: item.label || item.value || "",
      // Default to empty string if label is undefined
      value: item.value || ""
      // Default to empty string if value is undefined
    }));
  }
  return [];
}
export function escapeObjectForInlineBinding(obj) {
  return JSON.stringify(obj).replace(/'/g, "&#39;");
}
export function buildValidationRules(validationString) {
  validationString = validationString.replace(/^\[|]$/g, "").trim();
  if (!validationRulesRegex.test(validationString)) return "";
  const rules = [];
  let current = "";
  let depth = 0;
  for (let char of validationString) {
    if (char === "," && depth === 0) {
      if (current.trim()) rules.push(current.trim());
      current = "";
    } else {
      if (char === "(") depth++;
      if (char === ")") depth--;
      current += char;
    }
  }
  if (current.trim()) rules.push(current.trim());
  const formatted = rules.map((rule) => {
    rule = rule.trim();
    if (!rule.startsWith("rules.")) rule = `rules.${rule}`;
    if (!/\(.+\)$/.test(rule)) rule += "()";
    return rule.replace(/"/g, "'");
  });
  return `:rules="[${formatted.join(",")}]"`;
}
export function processDefaultTemplate(item, insideTemplate, optionString, validationRules, dataVariable = "data") {
  if (!validationRules) validationRules = item.validationRules ? buildValidationRules(item.validationRules) || "" : "";
  const hasVariant = some([item.inputAttributes], (str) => includes(str, "variant"));
  const defaultAttributes = `${!hasVariant ? `variant="underlined"` : ""} :active=isReadonly`;
  return `<${item.inputType} ${defaultAttributes} v-model="${dataVariable}.${item.variableName || ""}" label="${item.inputLabel || item.variableName || ""}"${item.inputAttributes ? " " + item.inputAttributes : ""}${optionString ? " " + optionString.trim() : ""}${validationRules ? " " + validationRules.trim() : ""}>${insideTemplate || ""}</${item.inputType}>`;
}
