<template>
  <el-dialog v-model="visible" title="规则设置">
    <div class="mb-8">
      <div>
        <h4>数据类型</h4>
        <el-radio-group v-model="state.tpl.dataType">
          <el-radio
            :label="item.value"
            v-for="(item, index) in state.dataTypeList"
            :key="index"
            >{{ item.label }}</el-radio
          >
        </el-radio-group>
      </div>
      <div class="mt-2">
        <template v-if="state.tpl.dataType == 'numeric'">
          数值区间:
          <el-input-number
            v-model="state.tpl.data.total.min"
            controls-position="right"
            :controls="false"
          />
          ~
          <el-input-number
            v-model="state.tpl.data.total.max"
            controls-position="right"
            :controls="false"
          />
        </template>
        <template v-if="state.tpl.dataType == 'string'">
          长度区间:
          <el-input-number
            v-model="state.tpl.data.total.min"
            :min="0"
            controls-position="right"
            :controls="false"
          />
          ~
          <el-input-number
            v-model="state.tpl.data.total.max"
            :min="0"
            controls-position="right"
            :controls="false"
          />
        </template>
        <template v-if="state.tpl.dataType == 'specific'">
          <el-select
            v-model="state.tpl.data.valueList"
            class="w-50 specific-select"
            multiple
            filterable
            allow-create
            default-first-option
            @keyup.native.enter.stop
          >
            <el-option
              v-for="item in state.valueList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <div>
            <el-button
              type="primary"
              class="mt-4"
              @click="oneKeyAdd(['阴性', '阳性'])"
              >一键添加阴阳</el-button
            >
          </div>
        </template>
      </div>
    </div>
    <div style="margin-bottom: 40px">
      <div>
        <h4>是否必填</h4>
        <el-radio-group v-model="state.tpl.dataTotal">
          <el-radio
            :label="item.value"
            v-for="(item, index) in state.dataTotalList"
            :key="index"
            :disabled="
              (state.tpl.dataType == 'numeric' ||
                state.tpl.dataType == 'specific') &&
              item.value == 'length'
            "
            >{{ item.label }}</el-radio
          >
        </el-radio-group>
      </div>
    </div>
    <template #footer>
      <el-button type="primary" @click="submit">保存</el-button>
    </template>
  </el-dialog>
</template>
<script setup>
import { computed, defineOptions, reactive, watch } from "vue";
import { ElMessage } from "element-plus";
defineOptions({
  name: "ComponentRegex"
});
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  }
});
const emits = defineEmits(["update:visible", "success"]);
const visible = computed({
  get() {
    return props.visible;
  },
  set(value) {
    emits("update:visible", value);
  }
});
const state = reactive({
  valueList: [],
  dataTypeList: [
    {
      label: "数字",
      value: "numeric"
    },
    {
      label: "字符串",
      value: "string"
    },
    {
      label: "特定值",
      value: "specific"
    }
  ],
  dataTotalList: [
    {
      label: "非必填",
      value: "not_required"
    },
    {
      label: "必填",
      value: "required"
    }
  ],
  testValue: "",
  tpl: {
    dataType: "numeric",
    data: {
      total: {
        min: 0,
        max: 0
      },
      valueList: []
    },
    dataTotal: "not_required"
  }
});

watch(
  () => state.tpl.dataType,
  () => {
    if (state.tpl.dataType != "string" && state.tpl.dataTotal == "length") {
      state.tpl.dataTotal = "not_required";
    }
  },
  {
    immediate: true,
    deep: true
  }
);
watch(
  () => visible.value,
  v => {
    if (!v) {
      state.tpl = {
        dataType: "numeric",
        data: {
          total: {
            min: 0,
            max: 0
          },
          valueList: []
        },
        dataTotal: "not_required"
      };
    }
  },
  { immediate: true }
);

const oneKeyAdd = (arr = []) => {
  state.tpl.data.valueList.push(...arr);
  state.tpl.data.valueList = [...new Set(state.tpl.data.valueList)];
};
const setTpl = n => {
  if (n && typeof n == "string") {
    try {
      n = JSON.parse(n);
    } catch (e) {
      console.log(e);
    }
  }
  for (let k in n) {
    if (!isNaN(k)) {
      delete n[String(k)];
    }
  }
  state.tpl = Object.assign(state.tpl, n);
  console.log(state.tpl);
  visible.value = true;
  // console.log(visible);
};
const check = (tpl, value) => {
  if (value.indexOf(" ") > -1) {
    return false;
  }
  // 数字区间判断
  if (tpl.dataType == "numeric" && (tpl.data.total.min || tpl.data.total.max)) {
    if (tpl.dataTotal == "required") {
      if (value == "") {
        return false;
      }
    } else {
      if (value == "") {
        return true;
      }
    }
    return value >= tpl.data.total.min && value <= tpl.data.total.max;
  }

  const mapData = {
    numeric_required:
      tpl.data.total.min == 0 && tpl.data.total.max == 0
        ? "(\\-|\\+)?[\\d]+(\\.\\d+)?"
        : `(\\-|\\+)?[\\d]{${tpl.data.total.min},${tpl.data.total.max}}(\\.\\d+)`,
    numeric_not_required:
      tpl.data.total.min == 0 && tpl.data.total.max == 0
        ? "(\\-|\\+)?[\\d]*(\\.\\d+)?"
        : `(\\-|\\+)?[\\d]{${tpl.data.total.min},${tpl.data.total.max}}(\\.\\d+)`,
    string_required:
      tpl.data.total.min == 0 && tpl.data.total.max == 0
        ? ".+"
        : `.{${tpl.data.total.min},${tpl.data.total.max}}`,
    string_not_required:
      tpl.data.total.min == 0 && tpl.data.total.max == 0
        ? ".*"
        : `.{${tpl.data.total.min},${tpl.data.total.max}}`,
    specific_required: `[${tpl.data.valueList.join("|")}]+`,
    specific_not_required: `[${tpl.data.valueList.join("|")}]*`
  };

  let regexStr = mapData[`${tpl.dataType}_${tpl.dataTotal}`];
  let regex = new RegExp(`^${regexStr}$`);
  let result = regex.test(state.testValue);
  return result;
};
const buildName = tpl => {
  let name = [];
  let index = state.dataTypeList.findIndex(i => i.value == tpl.dataType);
  if (index > -1) {
    name.push(`${state.dataTypeList[index].label}`);
  }

  index = state.dataTotalList.findIndex(i => i.value == tpl.dataTotal);
  if (index > -1) {
    name.push(`${state.dataTotalList[index].label}`);
  }

  return name.join("|");
};
const submit = () => {
  if (state.testValue) {
    let result = state.check(state.tpl, state.testValue);
    if (!result) {
      return ElMessage.error("测试未通过");
    }
  }
  console.log(state.tpl);
  emits("success", { ...state.tpl, name: buildName(state.tpl) });
  if (state.testValue) {
    ElMessage.success("测试通过");
  }

  visible.value = false;
};

defineExpose({
  setTpl
});
</script>
<style lang="scss">
.specific-select {
  .el-tag {
    white-space: normal;
    height: auto;
  }
}
</style>
