<template>
  <div class="gateway-form">
    <div class="gateway-form-item">
      <el-form
        :model="state.form.ruleRows"
        ref="form_ref"
        :rules="state.tableRules"
        label-width="0"
        style="width: 100%">
        <el-table :data="state.form.ruleRows" stripe border>
          <el-table-column
            v-for="header in ruleHeaders"
            :prop="header.prop"
            :key="header.prop"
            :label="header.label"
            :width="header.width">
            <template #default="{ $index }">
              <div class="warning-threshold" v-if="header.prop == 'warning_threshold'">
                <el-form-item :prop="`[${$index}].from`" :rules="state.tableRules.from($index)" style="flex: 1">
                  <el-input
                    style="flex: 1"
                    v-model="state.form.ruleRows[$index].from"
                    placeholder="请输入"
                    @input="inputNum($index, 'from')"
                    @blur="changeWarningThresholdFrom($index)">
                    <template v-if="!isEmptyOption" #append>{{
                      ruleTypeOptions[props.rule_type]?.unit || ""
                    }}</template>
                  </el-input>
                </el-form-item>
                <span class="to">-</span>
                <el-form-item label="" :prop="`${$index}.to`" :rules="state.tableRules.to($index)" style="flex: 1">
                  <el-input
                    style="flex: 1"
                    v-model="state.form.ruleRows[$index].to"
                    placeholder="请输入"
                    clearable
                    @input="inputNum($index, 'to')"
                    @blur="changeWarningThresholdTo($index)">
                    <template v-if="!isEmptyOption" #append>{{
                      ruleTypeOptions[props.rule_type]?.unit || ""
                    }}</template>
                  </el-input>
                </el-form-item>
              </div>
              <div v-else-if="header.prop == 'risk_level'">
                <el-form-item label="" :prop="`[${$index}].risk_level`" :rules="state.tableRules.risk_level">
                  <el-select style="flex: 1" v-model="state.form.ruleRows[$index].risk_level" placeholder="请选择">
                    <el-option
                      v-for="item in riskLevelOptions($index)"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id">
                    </el-option>
                  </el-select>
                </el-form-item>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="" label="操作" width="150px">
            <template #default="{ $index }">
              <div class="table-operation">
                <el-button
                  link
                  type="primary"
                  @click="createRule($index)"
                  :disabled="state.form.ruleRows.length >= riskLevels.length">
                  新增
                </el-button>
                <span class="line"></span>
                <el-button link type="primary" @click="removeRule($index)" :disabled="state.form.ruleRows.length == 1">
                  删除
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </el-form>
    </div>
  </div>
</template>

<script setup>
import { computed, nextTick, onBeforeMount, reactive, ref } from "vue";
import gapTitle from "@/components/gap-title.vue";
import { ElMessage } from "element-plus";
import { Empty, GetRuleTypeOptions } from "@/components/env.js";
const props = defineProps({
  form: {
    type: Object,
    default: null,
  },
  rule_type: {
    type: String,
    default: "1",
  },
});
const ruleTypeOptions = ref({});
const getRuleTypeOptions = async (cb) => {
  ruleTypeOptions.value = await GetRuleTypeOptions();
  cb && cb();
};
const validateFrom = (rule, value, callback, index) => {
  let thisRow = state.form.ruleRows[index];
  //   如果只有一条数据，并且上限下限都没有填写，则提示错误
  if (state.form.ruleRows.length == 1 && thisRow.from === "" && thisRow.to == "") {
    return callback(new Error("请输入"));
  }
  //   当前下限不是第一条数据，并且为空，提示错误
  if (index > 0 && value === "") {
    return callback(new Error("请输入"));
  }
  callback();
};
const validateTo = (rule, value, callback, index) => {
  let thisRow = state.form.ruleRows[index];
  //   如果只有一条数据，并且上限下限都没有填写，则提示错误
  if (state.form.ruleRows.length == 1 && thisRow.from === "" && thisRow.to == "") {
    return callback(new Error("请输入"));
  }
  //   当前上限不是最后一条数据，并且为空，提示错误
  if (index < state.form.ruleRows.length - 1 && value === "") {
    return callback(new Error("请输入"));
  }
  callback();
};
const state = reactive({
  form: {
    ruleRows: [],
  },
  tableRules: {
    from: (index) => {
      return [{ validator: (rule, value, callback) => validateFrom(rule, value, callback, index), trigger: "blur" }];
    },
    to: (index) => {
      return [{ validator: (rule, value, callback) => validateTo(rule, value, callback, index), trigger: "blur" }];
    },
    risk_level: [{ required: true, message: "请选择", trigger: "change" }],
  },
});
const form_ref = ref(null);
const Submit = async () => {
  let form_valid = await new Promise((resolve, reject) => {
    form_ref.value.validate((res) => resolve(res));
  });
  return form_valid;
};
const riskLevels = ref([
  {
    id: 4,
    name: "重大风险",
  },
  {
    id: 3,
    name: "较大风险",
  },
  {
    id: 2,
    name: "一般风险",
  },
  {
    id: 1,
    name: "低风险",
  },
]);
const riskLevelOptions = computed(() => {
  return (index) => {
    let risk_level = state.form.ruleRows[index].risk_level;
    let rows = state.form.ruleRows.map((e) => e.risk_level);
    if (risk_level) {
      let i = rows.findIndex((e) => e == risk_level);
      rows.splice(i, 1);
    }
    return riskLevels.value.filter((e) => !rows.includes(e.id));
  };
});
const ruleHeaders = [
  {
    prop: "warning_threshold",
    label: "预警阈值",
    width: "500px",
  },
  {
    prop: "risk_level",
    label: "风险程度",
  },
];
const createRule = (index = -1) => {
  state.form.ruleRows.splice(index + 1, 0, {
    from: "",
    to: "",
    risk_level: "",
  });
};
const setLimits = (index) => {
  let rows = [...state.form.ruleRows];
  rows.splice(index, 1);
  return (
    rows.map((e) => {
      return {
        down: e.from,
        up: e.to,
      };
    }) || []
  );
};
const isEmptyOption = computed(() => {
  return Empty(props.rule_type, ruleTypeOptions.value);
});
const limit = computed(() => {
  return (
    ruleTypeOptions.value[props.rule_type] || {
      down: "",
      up: "",
    }
  );
});
const changeWarningThresholdFrom = (index) => {
  let { down, up } = limit.value;
  let { from, to } = state.form.ruleRows[index];
  if (to !== "" && from !== "" && from > +to) {
    ElMessage.error(`下限不能大于上限`);
    state.form.ruleRows[index].from = "";
    return;
  } else if (down !== "" && +from < +down) {
    ElMessage.error(`下限不能小于${down}`);
    state.form.ruleRows[index].from = "";
    return;
  } else if (up != "" && +from > +up) {
    ElMessage.error(`上限不能超过${up}`);
    state.form.ruleRows[index].from = "";
    return;
  }
  let rows = setLimits(index);
  if (rows.length == 0) return;
  try {
    rows.forEach((e, i) => {
      if (from !== "") {
        if (i == 0 && e.down === "" && +from <= +e.up) {
          throw "";
        }
        if (e.up !== "" && e.down !== "" && +e.up >= +from && +from > +e.down) {
          throw "";
        }
      }
    });
  } catch (e) {
    ElMessage.error(`该范围已被设置`);
    state.form.ruleRows[index].from = "";
  }
};
const inputNum = (index, key) => {
  if (state.form.ruleRows[index][key] == "") return;
  if (state.form.ruleRows[index][key] == "-") return;
  state.form.ruleRows[index][key] = `${state.form.ruleRows[index][key]}`
    .replace(/[^\-?\d.]/g, "") //只允许输入负号，数字，小数点
    .replace(/(\-)+/, "$1") //过滤连续多个负号
    .replace(/(\.)+/, "$1") //过滤连续多个小数点
    .replace(/(\.\d+)\./g, "$1") //过滤出现多个小数点
    .replace(/(\d)\-/g, "$1"); //过滤处于非开头的负号
};
const changeWarningThresholdTo = (index) => {
  let { down, up } = limit.value;
  let { from, to } = state.form.ruleRows[index];
  if (to !== "" && from !== "" && from > +to) {
    ElMessage.error(`下限不能大于上限`);
    state.form.ruleRows[index].to = "";
    return;
  } else if (down !== "" && +to < +down) {
    ElMessage.error(`下限不能小于${down}`);
    state.form.ruleRows[index].to = "";
    return;
  } else if (up != "" && +to > +up) {
    ElMessage.error(`上限不能超过${up}`);
    state.form.ruleRows[index].to = "";
    return;
  }
  let rows = setLimits(index);
  if (rows.length == 0) return;
  try {
    rows.forEach((e, i) => {
      if (to !== "") {
        if (i == rows.length - 1 && e.up === "" && +to > +e.down) {
          throw "";
        }
        if (e.up !== "" && e.down !== "" && +e.up > +to && +to > +e.down) {
          throw "";
        }
      }
    });
  } catch (e) {
    ElMessage.error(`该范围已被设置`);
    state.form.ruleRows[index].to = "";
  }
};
const removeRule = (index) => {
  state.form.ruleRows.splice(index, 1);
};
const info = () => {
  if (!props.form || props.form?.length == 0) {
    getRuleTypeOptions();
    createRule();
    return;
  }
  getRuleTypeOptions(() => {
    state.form.ruleRows =
      props.form?.map((e) => {
        return {
          from: e.from,
          to: e.to,
          risk_level: e.risk_level,
        };
      }) || [];
    if (state.form.ruleRows.length == 0) {
      createRule();
    }
  });
};
onBeforeMount(() => {
  info();
});
defineExpose({
  Submit,
  form: state.form,
  form_ref,
});
</script>

<style lang="scss" scoped>
.gateway-form {
  margin-bottom: 16px;
  :deep(.gap-title) {
    margin-bottom: 16px;
  }
  &-item {
    max-width: 1080px;
    width: 100%;
    padding-left: 120px;
    :deep(.el-table thead th) {
      background-color: #f5f6f9;
    }
    .indicator-expression {
      height: 300px;
      width: 100%;
      :deep(.vue-ace-editor) {
        margin-top: 0;
      }
    }
  }
}
:deep(.el-form-item) {
  margin-bottom: 0 !important;
}
.warning-threshold {
  display: flex;
  align-items: center;
  :deep(.el-input__wrapper) {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
  }
  :deep(.el-input-group__append, .el-input-group__prepend) {
    border-radius: 4px;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
}
.to {
  margin: 0 16px;
}
.line {
  width: 1px;
  height: 14px;
  background-color: #c1c7d7;
  margin: 0 16px;
  display: inline-block;
}
.rule-table {
  :deep(.el-table thead th) {
    background-color: #f5f6f9;
  }
}
</style>
