<template>
  <div class="custom-form">
    <el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="120px">
      <div class="custom-form-item">
        <el-form-item label="预警分类" prop="warn_target">
          <el-input
            v-model="state.form.warn_target"
            placeholder="请输入预警分类"
            :disabled="isEdit"
            :maxlength="20"
            show-word-limit
            clearable
            @change="changeWarnCustomTarget"></el-input>
        </el-form-item>
        <el-form-item label="预警对象" prop="warn_type">
          <el-input
            v-model="state.form.warn_type"
            placeholder="请输入预警对象"
            :disabled="isEdit"
            clearable
            :maxlength="20"
            show-word-limit
            @change="changeWarnCustomType"></el-input>
        </el-form-item>
        <el-form-item label="预警指标" prop="warn_indicator">
          <el-input
            v-model="state.form.warn_indicator"
            placeholder="请输入预警指标"
            :disabled="isEdit"
            :maxlength="30"
            show-word-limit
            clearable
            @change="changeWarnCustomType"></el-input>
        </el-form-item>
      </div>
      <gap-title :hasLine="true" title="指标表达式"> </gap-title>
      <div class="custom-form-item">
        <el-form-item label="" prop="indicator_expression">
          <div class="indicator-expression">
            <bg-code-editor v-model="state.form.indicator_expression"></bg-code-editor>
          </div>
        </el-form-item>
      </div>
      <gap-title :hasLine="true" title="预警规则"></gap-title>
      <div class="custom-form-item">
        <el-form-item label="预警规则类型" prop="rule_type">
          <el-select
            style="flex: 1"
            v-model="state.form.rule_type"
            placeholder="请选择"
            filterable
            @change="changeRuleType">
            <el-option v-for="(value, key) in ruleTypeOptions" :key="key" :label="value.label" :value="key">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="风险程度" prop="risk_level" v-if="isEmpty">
          <el-select style="flex: 1" v-model="state.form.risk_level" placeholder="请选择风险程度" filterable>
            <el-option v-for="item in riskLevels" :key="item.id" :label="item.name" :value="item.id"> </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="" v-else-if="state.form.ruleRows.length > 0">
          <div class="rule-table" style="width: 100%">
            <el-form
              :model="state.form.ruleRows"
              ref="table_form"
              :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 #append>{{ unitMap }}</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 #append>{{ unitMap }}</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>
        </el-form-item>
      </div>
    </el-form>
  </div>
</template>

<script setup>
import { computed, onBeforeMount, reactive, ref } from "vue";
import gapTitle from "@/components/gap-title.vue";
import { ElMessage } from "element-plus";
import { GetRuleTypeOptions, Empty } from "@/components/env.js";
const props = defineProps({
  form: {
    type: Object,
    default: null,
  },
  isEdit: {
    type: Boolean,
    default: false,
  },
});
var validateWarnIndex = (rule, value, callback) => {
  if (value === "") {
    if (state.form.type_key == "static") {
      callback(new Error("请选择"));
    } else {
      callback(new Error("请输入"));
    }
  } else {
    callback();
  }
};
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 ruleTypeOptions = ref({});
const state = reactive({
  form: {
    warn_target: "",
    warn_type: "",
    warn_indicator: "",
    indicator_expression: "",
    rule_type: "",
    ruleRows: [],
    risk_level: "",
  },
  rules: {
    warn_target: [{ required: true, message: "请输入预警分类", trigger: "blur" }],
    warn_type: [{ required: true, message: "请输入预警对象", trigger: "blur" }],
    rule_type: [{ required: true, message: "请选择预警规则类型", trigger: "change" }],
    warn_indicator: [{ validator: validateWarnIndex, trigger: "blur" }],
    indicator_expression: [{ required: true, message: "请输入预警指标", trigger: "blur" }],
    risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }],
  },
  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 isEmpty = computed(() => {
  return Empty(state.form.rule_type, ruleTypeOptions.value);
});
const changeWarnCustomTarget = () => {};
const changeWarnCustomType = () => {};
const setLimits = (index) => {
  let rows = [...state.form.ruleRows];
  rows.splice(index, 1);
  return (
    rows.map((e) => {
      return {
        down: +e.from,
        up: +e.to,
      };
    }) || []
  );
};
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 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) => {
      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 changeWarningThresholdTo = (index) => {
  let { down, up } = limit.value;
  let { from, to } = state.form.ruleRows[index];
  if (from != "" && 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) => {
      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) {
    state.form.ruleRows[index].to = "";
  }
};
const changeRuleType = () => {};
const form_ref = ref(null);
const table_form = ref(null);
const Submit = async () => {
  let form_valid = await new Promise((resolve, reject) => {
    form_ref.value.validate((res) => resolve(res));
  });
  if (isEmpty.value) {
    return form_valid;
  }
  let table_form_valid = await new Promise((resolve, reject) => {
    table_form.value.validate((res) => resolve(res));
  });
  return form_valid && table_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 unitMap = computed(() => {
  return ruleTypeOptions.value[state.form.rule_type]?.unit || "";
});
const limit = computed(() => {
  return (
    ruleTypeOptions.value[state.form.rule_type].limit || {
      down: "",
      up: "",
    }
  );
});
const getRuleTypeOptions = async () => {
  ruleTypeOptions.value = await GetRuleTypeOptions();
};
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 removeRule = (index) => {
  state.form.ruleRows.splice(index, 1);
};
const info = () => {
  if (!props.form) {
    createRule();
    return;
  }
  state.form.warn_target = props.form.warn_target;
  state.form.warn_type = props.form.warn_type;
  state.form.warn_indicator = props.form.warn_indicator;
  state.form.indicator_expression = props.form.indicator_expression;
  state.form.rule_type = props.form.rule_type;
  state.form.risk_level = props.form.risk_level;
  state.form.ruleRows =
    props.form?.ruleRows?.map((e) => {
      return {
        from: e.from,
        to: e.to,
        risk_level: e.risk_level,
      };
    }) || [];
  if (state.form.ruleRows.length == 0) {
    createRule();
  }
};
const formatForm = computed(() => {
  return {
    ...state.form,
    isEmpty: isEmpty.value,
  };
});
onBeforeMount(() => {
  getRuleTypeOptions();
  info();
});
defineExpose({
  Submit,
  form: formatForm,
  form_ref,
});
</script>

<style lang="scss" scoped>
.custom-form {
  :deep(.gap-title) {
    margin-bottom: 16px;
  }
  &-item {
    max-width: 1080px;
    width: 100%;
    padding-left: 8px;
    .indicator-expression {
      height: 300px;
      width: 100%;
      :deep(.vue-ace-editor) {
        margin-top: 0;
      }
    }
  }
}
.warning-threshold {
  display: flex;
  align-items: center;
  :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>
