import { isArray, isNumber, cloneDeep } from 'lodash-es';
import { FormDesignApi } from '../api/FormDesignApi';

/**
 * 生成key
 * @param [formItem] 需要生成 key 的控件，可选，如果不传，默认返回一个唯一 key
 * @returns {string|boolean} 返回一个唯一 id 或者 false
 */
export async function generateKey(formItem) {
  if (formItem) {
    const itemId = await FormDesignApi.genId();
    formItem.itemId = itemId;
    formItem.fieldCode = itemId || '';
    return true;
  }
  return '';
}

/**
 * 驼峰转下划线
 * @param str
 */
export function toLine(str) {
  return str.replace(/([A-Z])/g, '_$1').toLowerCase();
}

/**
 * 生成唯一guid
 * @returns {String} 唯一id标识符
 */
export function randomUUID() {
  function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  }
  return `${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4() + S4() + S4()}`;
}

/**
 * 遍历表单项
 * @param array
 * @param cb
 */
export function formItemsForEach(array, cb) {
  if (!isArray(array)) return;
  const traverse = formItems => {
    formItems.forEach(formItem => {
      if (['grid'].includes(formItem.componentCode)) {
        // 栅格布局
        formItem.columns?.forEach(item => traverse(item.children));
      } else {
        cb(formItem);
      }
    });
  };
  traverse(array);
}

/**
 * 移除数组中指定元素，value可以是一个数字下标，也可以是一个函数，删除函数第一个返回true的元素
 * @param array  需要移除元素的数组
 * @param value
 * @returns 返回删除的数组项
 */
export function removeItem(array, value) {
  let removeVal = [];
  if (!isArray(array)) return undefined;
  if (isNumber(value)) {
    removeVal = array.splice(value, 1);
  } else {
    const index = array.findIndex(value);
    if (index !== -1) {
      removeVal = array.splice(index, 1);
    }
  }
  return removeVal.shift();
}

/**
 * 将校验规则中的正则字符串转换为正则对象
 * @param rules
 * @return
 */
export const strToReg = rules => {
  const newRules = cloneDeep(rules);
  return newRules.map(item => {
    if (item.pattern) item.pattern = runCode(item.pattern);
    return item;
  });
};

/**
 * 执行一段字符串代码，并返回执行结果，如果执行出错，则返回该参数
 * @param code
 * @return {any}
 */
export const runCode = code => {
  try {
    return new Function(`return ${code}`)();
  } catch {
    return code;
  }
};

/**
 * 处理异步选项属性，如 select treeSelect 等选项属性如果传递为函数并且返回Promise对象，获取异步返回的选项属性
 * @param {} options
 * @return {}
 */
export const handleAsyncOptions = async options => {
  try {
    if (isFunction(options)) return await options();
    return options;
  } catch {
    return [];
  }
};

/**
 * 判断树形结构中的formItems中fieldCode是否为空
 * @param {Array} formItems - 表单项数组
 * @param {string} fieldCode - 要判断的字段
 * @param {Array} excludeList - 不需要判断的字段列表
 * @param {string} compareType - 用来判断的类型
 * @returns {boolean} - 如果有空的fieldCode返回true，否则返回false
 */
export function isParamEmpty(formItems, fieldCode, excludeList, compareType) {
  for (const item of formItems) {
    // 检查当前项的类型是否在排除列表中
    if (!excludeList.includes(item[compareType])) {
      // 检查fieldCode是否为空或未定义
      if (item.bindFieldFlag && (!item[fieldCode] || item[fieldCode].trim() === '')) {
        return true; // 找到一个空的fieldCode
      }
    }

    // 如果有子项，递归检查子项
    if (Array.isArray(item.children) && item.children.length > 0) {
      if (isParamEmpty(item.children, fieldCode, excludeList, compareType)) {
        return true; // 在子项中找到空的fieldCode
      }
    }
  }
  return false; // 没有找到空的fieldCode
}
