import { t } from '@/shared/i18n';
import { LAYOUT_FIELDS, RESTRICTED_FIELDS } from './store';

/**
 * Create a layout structure from a flat list of fields
 */
export function createLayout(fields) {
  let layout = {
    tabs: [],
  };

  let tab = null;
  let section = null;
  let column = null;

  function getRandomId(length = 8) {
    const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

  function createDf(fieldtype, fieldname = "", label = "") {
    return {
      name: getRandomId(8),
      fieldtype: fieldtype,
      fieldname: fieldname,
      label: label,
      __islocal: 1,
      __unsaved: 1,
    };
  }

  function setTab(df) {
    tab = getNewTab(df);
    column = null;
    section = null;
    layout.tabs.push(tab);
  }

  function setSection(df) {
    if (!tab) setTab();

    section = getNewSection(df);
    column = null;
    tab.sections.push(section);
  }

  function setColumn(df) {
    if (!section) setSection();

    column = getNewColumn(df);
    section.columns.push(column);
  }

  function getNewTab(df) {
    let _tab = {};
    _tab.df = df || createDf("Tab Break", "", t("Details"));
    _tab.sections = [];
    _tab.is_first = !df;
    return _tab;
  }

  function getNewSection(df) {
    let _section = {};
    _section.df = df || createDf("Section Break");
    _section.columns = [];
    _section.is_first = !df;
    return _section;
  }

  function getNewColumn(df) {
    let _column = {};
    _column.df = df || createDf("Column Break");
    _column.fields = [];
    _column.is_first = !df;
    return _column;
  }

  for (let df of fields) {
    if (df.fieldname) {
      // make a copy to avoid mutation bugs
      df = JSON.parse(JSON.stringify(df));
    }

    if (df.fieldtype === "Tab Break") {
      setTab(df);
    } else if (df.fieldtype === "Section Break") {
      setSection(df);
    } else if (df.fieldtype === "Column Break") {
      setColumn(df);
    } else {
      if (!column) setColumn();

      let field = { df: df };

      if (df.fieldtype === "Table") {
        field.table_columns = getTableColumns(df);
      }

      column.fields.push(field);
      section.has_fields = true;
    }
  }

  // remove empty sections
  for (let tab of layout.tabs) {
    for (let i = tab.sections.length - 1; i >= 0; --i) {
      let section = tab.sections[i];
      if (!section.has_fields) {
        tab.sections.splice(tab.sections.indexOf(section), 1);
      }
    }
  }

  // Ensure at least one tab with one section and one column
  if (layout.tabs.length === 0) {
    layout.tabs.push({
      df: createDf("Tab Break", "", t("Details")),
      sections: [sectionBoilerplate(createDf)],
      is_first: true,
    });
  }

  return layout;
}

/**
 * Get table columns for a Table field
 */
export function getTableColumns(df, childPagetype) {
  let tableColumns = [];

  // For now, return a simple structure
  // This can be enhanced later to fetch actual child pagetype fields
  tableColumns.push([
    {
      label: t("No."),
    },
    1,
  ]);

  return tableColumns;
}

/**
 * Evaluate depends_on expression
 * @param {string|boolean|function} expression - The depends_on expression
 * @param {object} pg - The current field/document being evaluated (usually selected_field)
 * @param {object} parent - Optional parent document (usually the PageType record)
 */
export function evaluateDependsOnValue(expression, pg, parent = null) {
  if (!pg) return false;

  let out = null;

  if (typeof expression === "boolean") {
    out = expression;
  } else if (typeof expression === "function") {
    out = expression(pg);
  } else if (expression.substr(0, 5) === "eval:") {
    try {
      // Define in_list function for eval context
      const in_list = (list, value) => list && list.includes(value);
      // Simple evaluation for common patterns
      out = eval(expression.substr(5));
    } catch (e) {
      // If evaluation fails (e.g., parent is null), return false
      // This is expected for conditions like "parent.is_submittable" when parent is not yet loaded
      out = false;
    }
  } else {
    const value = pg[expression];
    if (Array.isArray(value)) {
      out = !!value.length;
    } else {
      out = !!value;
    }
  }

  return out;
}

/**
 * Create a section boilerplate with one column
 */
export function sectionBoilerplate(getDf) {
  return {
    df: getDf("Section Break"),
    columns: [
      {
        df: getDf("Column Break"),
        fields: [],
      },
    ],
  };
}

/**
 * Move children to a new parent element
 */
export function moveChildrenToParent(props, parent, child, currentContainer, getDf) {
  let children = props[parent][child + "s"];
  let index = children.indexOf(props[child]);

  if (index > 0) {
    const name = parent.charAt(0).toUpperCase() + parent.slice(1);
    // move current children and children after that to a new parent
    let newParent = {
      df: getDf(name + " Break"),
      [child + "s"]: children.splice(index),
    };

    // add new parent after current parent
    let parents = currentContainer[parent + "s"];
    let parentIndex = parents.indexOf(props[parent]);
    parents.splice(parentIndex + 1, 0, newParent);

    // remove current child and after that
    children.splice(index + 1);

    return newParent.df.name;
  }
}

/**
 * Scrub field names - generate fieldnames from labels if missing
 */
export function scrubFieldNames(fields) {
  function getRandomStr(length = 4) {
    const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

  fields.forEach((d) => {
    if (d.fieldtype) {
      if (!d.fieldname) {
        if (d.label) {
          d.fieldname = d.label.trim().toLowerCase().replaceAll(" ", "_");
          if (d.fieldname.endsWith("?")) {
            d.fieldname = d.fieldname.slice(0, -1);
          }
          if (RESTRICTED_FIELDS.includes(d.fieldname)) {
            d.fieldname = d.fieldname + "1";
          }
          if (d.fieldtype === "Section Break") {
            d.fieldname = d.fieldname + "_section";
          } else if (d.fieldtype === "Column Break") {
            d.fieldname = d.fieldname + "_column";
          } else if (d.fieldtype === "Tab Break") {
            d.fieldname = d.fieldname + "_tab";
          }
        } else {
          d.fieldname =
            d.fieldtype.toLowerCase().replaceAll(" ", "_") +
            "_" +
            getRandomStr(4);
        }
      } else {
        if (RESTRICTED_FIELDS.includes(d.fieldname)) {
          throw new Error(t("Fieldname {0} is restricted").replace("{0}", d.fieldname));
        }
      }
      let regex = new RegExp(/['",./%@()<>{}]/g);
      d.fieldname = d.fieldname.replace(regex, "");
      // fieldnames should be lowercase
      d.fieldname = d.fieldname.toLowerCase();
    }

    // unique is automatically an index
    if (d.unique) {
      d.search_index = 0;
    }
  });

  return fields;
}

/**
 * Clone a field with a new unique name
 */
export function cloneField(field) {
  function getRandomId(length = 8) {
    const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

  let clonedField = JSON.parse(JSON.stringify(field));
  clonedField.df.name = getRandomId(8);
  return clonedField;
}

/**
 * Show a confirmation dialog
 */
export function confirmDialog(
  title,
  message,
  primaryAction,
  primaryActionLabel,
  secondaryAction,
  secondaryActionLabel
) {
  // This will be implemented with naive-ui dialog
  // For now, use browser confirm
  if (window.confirm(`${title}\n\n${message}`)) {
    primaryAction && primaryAction();
  } else {
    secondaryAction && secondaryAction();
  }
}

/**
 * Check if the device has a touch screen
 */
export function isTouchScreenDevice() {
  return "ontouchstart" in document.documentElement;
}

/**
 * Check if a value is in a list
 */
export function inList(list, value) {
  return list && list.includes(value);
}
