import {isBlank} from "@/utils/common";
import {testFormulaValidation} from "@/api/business/crm/paraValidation/paraValidation";

let funList = [
  {
    name: 'SUM',
    value: 'SUM_FUNC',
    tip:"入参：至少一位入参，多个则以\",\"隔开，" +
      "作用：用于求和",
  },
  {
    name: 'IF',
    value: 'IF_FUNC',
    tip:"入参： 参数1) 表示计算结果为真或假的任意值或表达式," +
              " 参数2) 当参数1为真时返回的值" +
              " 参数3) 当参数1为假时返回的值"+
      " 作用：根据指定的条件来判断其“真”(1)、“假”(0)，并根据逻辑计算的真假值返回相应的内容",
  },
  {
    name: 'IFS',
    value: 'IFS_FUNC',
    tip:"入参：至少两位入参，且一定是偶数个入参，" +
        " 语法：IFS(logical_test1,value_if_true1,[logical_test2,value_if_true2,...])" +
        " logical_test1是逻辑表达式，value_if_true1是当logical_test1为真时返回的值，"
  },
  {
    name: 'MAX',
    value: 'MAX_FUNC',
    tip: "入参：至少一位入参，多个则以\",\"隔开，" +
      " 作用：用于求最大值",
  },
  {
    name: 'MIN',
    value: 'MIN_FUNC',
    tip: "入参：至少一位入参，多个则以\",\"隔开，" +
      " 作用：用于求最小值",
  },
  {
    name: 'FIND',
    value: 'FIND_FUNC',
    tip: "入参：有且仅能有三个入参" +
      " 语法：FIND(searchByStr,searchStr,startIndex)" +
      " searchByStr是被查找的字符串，searchStr是要查找的字符串，startIndex是开始查找的位置，如果能查找到，则返回searchStr中查找到的位置，如果不能，则返回-1",
  },
  {
    name: 'ROUND',
    value: 'ROUND_FUNC',
    tip:"入参，至多两个入参，最少一个" +
      " 语法：ROUND(number,decimalPlaces)" +
      " number是要四舍五入的数字，decimalPlaces是保留的小数位数，如果decimalPlaces为空，则默认为0"
  },
  {
    name: 'ROUNDUP',
    value: 'CEIL_FUNC',
    tip:"入参：有且仅能有一个入参" +
      " 作用：用于向上取整"
  },
  {
    name: 'ROUNDDOWN',
    value: 'FLOOR_FUNC',
    tip:"入参：有且仅能有一个入参" +
      " 作用：用于向下取整"
  },
  {
    name: 'ISEMPTY',
    value: 'IS_EMPTY_FUNC',
    tip:"入参：有且仅能有一个入参" +
      " 作用：判断字符串是否为空"
  },
  {
    name:"INCLUDE",
    value:"INCLUDE_FUNC",
    tip:"入参：有且仅能有两个入参" +
      "作用：用于查询在第二个入参中，以\";\"分割后的每个字符串是否有任一字符串完全等于第一个入参"
  }
]
let funKeyMap = {
  'SUM': 'SUM_FUNC',
  'IFS': 'IFS_FUNC',
  'IF': 'IF_FUNC',
  'MAX': 'MAX_FUNC',
  'MIN': 'MIN_FUNC',
  'FIND': 'FIND_FUNC',
  'ROUND': 'ROUND_FUNC',
  'ROUNDUP': 'CEIL_FUNC',
  'ROUNDDOWN': 'FLOOR_FUNC',
  'ISEMPTY': 'IS_EMPTY_FUNC',
  'INCLUDE': 'INCLUDE_FUNC'

}
let funValueMap = {
  'SUM_FUNC': 'SUM',
  'IFS_FUNC': 'IFS',
  'IF_FUNC': 'IF',
  'MAX_FUNC': 'MAX',
  'MIN_FUNC': 'MIN',
  'FIND_FUNC': 'FIND',
  'ROUND_FUNC': 'ROUND',
  'CEIL_FUNC': 'ROUNDUP',
  'FLOOR_FUNC': 'ROUNDDOWN',
  'IS_EMPTY_FUNC': 'ISEMPTY',
  'INCLUDE_FUNC': 'INCLUDE'

}
let logicOperation = [
  {
    name: 'AND',
    value: '&&'
  },
  {
    name: 'OR',
    value: '||'
  }
]
let logicKeyMap = {
  'AND': '&&',
  'OR': '||'
}
let logicValueMap;
logicValueMap = {
  '&&': 'AND',
  '||': 'OR'
}
/**
 * @description: 循环中 构造参数 正则匹配
 * @author: jubs 😀
 * @date: 2024/6/12 13:14
 * @return RegExp
 * @param label 参数code
 **/
function initRegpx(label) {
  // 'i' 表示不区分大小写
  // (?=(?:[^"]*"[^"]*")*[^"]*$) 排除被双引号包裹的情况
  return new RegExp(`(?<!\p{L})${label}(?!\p{L})(?=(?:[^"]*"[^"]*")*[^"]*$)`, 'g')
}
/**
 * @description: 循环中 构造方法 正则匹配
 * @author: jubs 😀
 * @date: 2024/6/12 13:15
 * @return RegExp
 * @param label 方法code
 **/
function initFuncRegpx(label){
  return new RegExp(`\\b${label}\\b(?!\p{L})(?=(?:[^"]*"[^"]*")*[^"]*$)`, 'g')
}

/**
 * @description: 公式解析
 * @author: jubs 😀
 * @date: 2024/6/7 17:23
 * @param formulaStr 解析前公式
 * @param replaceCodeList 解析前公式中需要替换的代码，包含这函数、参数list、逻辑操作符
 * @return 解析后的公式
 **/
function analysisFormula(formulaStr, replaceCodeList) {
  let fomula = formulaStr;
  let funcKey = Object.keys(funKeyMap);
  let logicKey = Object.keys(logicKeyMap);
  console.log(formulaStr, replaceCodeList)
  replaceCodeList.forEach(item => {
    if (fomula.indexOf(item.name) > -1) {
      if (logicKey.includes(item.name)) {
        let searchStr = new RegExp(` ${item.name.trim()}(?=(?:[^"]*"[^"]*")*[^"]*$) `,'g' )
        fomula = fomula.replaceAll(searchStr, item.value);
      }
      if (funcKey.includes(item.name)) {
        let searchStr = initFuncRegpx(item.name)
        fomula = fomula.replaceAll(searchStr, '$@$' + item.value + '$@$');
      }
      if (!funcKey.includes(item.name) && !logicKey.includes(item.name)) {
        let searchStr = initRegpx(item.name)
        fomula = fomula.replaceAll(searchStr, '$_$' + item.value + '$_$');
      }
    }
  })
  return fomula;
}



/**
 * @description: 加载参与替换的list
 * @author: jubs 😀
 * @date: 2024/6/7 17:25
 * @param paramsList 区域提醒 公用的参数list
 * @return 加载参与替换的list 加入了 方法、逻辑
 **/
function initReplaceCodeList(paramsList) {
  let replaceCode;
  let funcCodeList = Object.keys(funKeyMap).map(item => {
    return {
      name: item,
      value: funKeyMap[item],
      inputType:null,
    }
  })

  let logicList = Object.keys(logicKeyMap).map(item => {
    return {
      name: item,
      value: logicKeyMap[item],
      inputType:null,
    }
  })
  //变量code替换；
  let sortParamsList = paramsList.map(item => {
    return {
      name: item.name.replaceAll("(", "（").replaceAll(")", "）"),
      value: item.value,
      inputType: item.inputType,
    }
  });
  replaceCode = [...funcCodeList, ...logicList, ...sortParamsList]
  replaceCode = sortByKey(replaceCode, 'value');
  return replaceCode;
}


async function testSubmitCheckFunction(_this,formulaStr, paramsList,testFormula,usedParamsList) {
  let replaceCode = [];
  replaceCode = initReplaceCodeList(paramsList);
  let formulaValueTypeMap={}
  // @Date 2024/6/13 14:30 @Author jubs 😀 @description: 处理用户在不输入的情况下 点击了提交按钮
  for(let item of usedParamsList){
    if(isBlank(testFormula[`$_$${item.value}$_$`])){
      _this.$set(testFormula,`$_$${item.value}$_$`,null);
    }
    _this.$set(formulaValueTypeMap,`$_$${item.value}$_$`,item.inputType);
  }
  console.log(formulaValueTypeMap,'formulaValueTypeMap')
  console.log(usedParamsList,'usedParamsList')

  let formula = analysisFormula(formulaStr, replaceCode);
  let {data} = await testFormulaValidation({
    formulaValueStr: formula.replaceAll("，", ","),
    formulaValueMap: testFormula,
    formulaValueTypeMap:formulaValueTypeMap,
  });
  _this.testResult = data.calculateValue;
  if (_this.testResult === 'NaN' || data.result === 'NG') {
    _this.testResult = "NG";
  } else {
    _this.testResult = `OK-${data.objectCalculateValue}`;
  }
  return new Promise((resolve, reject) => {
    if (data) {
      if (data.result && data.result === 'NG') {
        _this.$message.error(_this.$t('validation.errorMsg'));
        reject(_this.$t('validation.errorMsg'));
      } else {
        resolve();
      }
    } else {
      reject(_this.$t('validation.errorMsg'));
    }
  })
}

function getContent(_this){
  if (isBlank(_this.formulaValueStr)) {
    return;
  }
  _this.usedParamsList = [];
  let formula = _this.formulaValueStr;
  let params=initReplaceCodeList(_this.paramsList);
  formula= analysisFormula(formula, params);
  _this.formulaValueStr = formula;
  let usedParamsList = _this.getParam(formula);
  const valueSet = new Set(usedParamsList)
  usedParamsList = Array.from(valueSet);
  console.log(usedParamsList, params)
  for (let value of usedParamsList) {
    let item = params.find(item => item.value === value.replaceAll('$_$', ''));
    if (item) {

      _this.usedParamsList.push({
        name: item.name,
        value: item.value,
        inputType: item.inputType,
        key: item.value
      })
    }
  }
  _this.$refs.testResult.open(true);
}


function getParam(str) {
  let matchList = [];
  const regex = /(\$_\$.*?\$_\$)/g;
  const matches = str.match(regex);
  if (matches) {
    matches.forEach(match => {
      matchList.push(match)
    });
  }
  return matchList;
}

function sortByKey(array, key) {
  return array.sort(function (a, b) {
    var x = !isBlank(key) ? a[key].length : a.length;
    var y = !isBlank(key) ? b[key].length : b.length;
    return ((x > y) ? -1 : ((x < y) ? 1 : 0));
  });
}


function matchStr(str) {
  //判断str中有没有 中文
  return /[\u4e00-\u9fa5]/g.test(str);
}


function isValidString(str) {
  // 判断是否含有中文字符
  if (/[\u4e00-\u9fa5]/.test(str)) {
    // 判断是否包含双引号包裹的中文字符
    if (/".*[\u4e00-\u9fa5].*"/.test(str)) {
      return true;
    } else {
      return false;
    }
  }
  return true;
}

export {
  funList,
  funKeyMap,
  funValueMap, logicOperation,
  logicKeyMap,
  logicValueMap,
  analysisFormula,
  initReplaceCodeList,
  matchStr,
  testSubmitCheckFunction,
  getContent,
  isValidString,
  initFuncRegpx

}
