<template>
  <el-form :model="state.form.warningScopeRows" ref="form_ref" :rules="tableRules" label-width="0" style="width: 100%">
    <el-table :data="state.form.warningScopeRows" stripe border empty-text="请输入表达式，根据表达式$...$自动生成表格">
      <el-table-column
        v-for="header in warningScopeHeaders"
        :prop="header.prop"
        :key="header.prop"
        :label="header.label"
        :width="header.width">
        <template #default="{ $index }">
          <div v-if="header.prop == 'indicator_tag'">
            <el-form-item :prop="`[${$index}].input_indicator_tag`" :rules="tableRules.input_indicator_tag">
              <div class="indictor-tag">
                <el-popover
                  :visible="state.form.warningScopeRows[$index].visible"
                  popper-class="cascader-operation"
                  placement="bottom-start">
                  <template #reference>
                    <el-input
                      v-model="state.form.warningScopeRows[$index].input_indicator_tag"
                      placeholder="请选择指标标签"
                      :ref="
                        (i_el) => {
                          inputRef[$index] = i_el;
                        }
                      "
                      @blur="blurInput($index)"
                      @focus="inputLabel($index, false)"
                      @input="inputLabel($index, true)"></el-input>
                  </template>
                  <div class="filter-first-tree-lists">
                    <ul class="bg-scroll" v-show="dataTree($index).length > 0">
                      <li
                        v-for="data in dataTree($index)"
                        :key="data"
                        :class="{ active: state.form.warningScopeRows[$index].indicator_scope == data.label }">
                        <div class="first-label-main" @click="chooseTreeFirst($index, data)">
                          <div class="tree-label">{{ data.label }}</div>
                          <div class="tree-icon">
                            <bg-icon
                              style="font-size: 16px; color: #404a62"
                              class="is-loading"
                              :class="{ 'loading-show': data.isLoading }"
                              icon="#bg-ic-loading"></bg-icon>
                            <bg-icon style="font-size: 14px; color: #404a62" icon="#bg-ic-arrow-right"></bg-icon>
                          </div>
                        </div>
                      </li>
                    </ul>
                    <ul v-show="dataTree($index).length == 0">
                      <li class="no-data">未查询到相关指标范围数据</li>
                    </ul>
                    <ul class="bg-scroll" v-show="state.form.warningScopeRows[$index].lastOptions?.length > 0">
                      <li
                        v-for="child in state.form.warningScopeRows[$index].lastOptions"
                        :key="child"
                        @click="chooseTreeLast(child, $index, false)"
                        :class="{ active: state.form.warningScopeRows[$index].indicator_tag == child }">
                        {{ child }}
                      </li>
                    </ul>
                  </div>
                </el-popover>
              </div>
            </el-form-item>
          </div>
          <div v-else-if="header.prop == 'cname'">
            <el-form-item :prop="`[${$index}].cname`" :rules="tableRules.cname">
              <el-input
                style="flex: 1"
                v-model="state.form.warningScopeRows[$index].cname"
                :maxlength="20"
                show-word-limit
                placeholder="请输入中文名称">
              </el-input>
            </el-form-item>
          </div>
          <div v-else-if="header.prop == 'is_required'">
            <el-form-item :prop="`[${$index}].is_required`" :rules="tableRules.is_required">
              <el-select v-model="state.form.warningScopeRows[$index].is_required" placeholder="请选择" style="flex: 1">
                <el-option v-for="(value, key) in tableSelOptions" :key="key" :label="value" :value="key"> </el-option>
              </el-select>
            </el-form-item>
          </div>
          <div v-else-if="header.prop == 'is_linkage'">
            <el-form-item :prop="`[${$index}].is_linkage`" :rules="tableRules.is_linkage">
              <el-select v-model="state.form.warningScopeRows[$index].is_linkage" placeholder="请选择" style="flex: 1">
                <el-option v-for="(value, key) in tableSelOptions" :key="key" :label="value" :value="key"> </el-option>
              </el-select>
            </el-form-item>
          </div>
        </template>
      </el-table-column>
    </el-table>
  </el-form>
</template>

<script setup>
import { reactive, watch, nextTick, computed, ref, onMounted } from "vue";
import { ElMessage } from "element-plus";
import axios from "@/request/http.js";

const props = defineProps({
  indicator_expression: {
    type: String,
    default: "",
  },
  warningScopeRows: {
    type: Array,
    default: () => [],
  },
});
// 是否是必填和是否联动下拉数据
const tableSelOptions = ["否", "是"];
// 表格表头
const warningScopeHeaders = [
  {
    prop: "key",
    label: "变量名称",
    width: 100,
  },
  {
    prop: "indicator_tag",
    label: "指标标签",
  },
  {
    prop: "cname",
    label: "中文名称",
  },
  {
    prop: "is_required",
    label: "是否必填",
    width: 150,
  },
  {
    prop: "is_linkage",
    label: "是否联动",
    width: 150,
  },
];
// 表单数据
const state = reactive({
  form: {
    warningScopeRows: [],
  },
});
// 表单验证
const tableRules = {
  input_indicator_tag: [{ required: true, message: "请输入", trigger: "blur" }],
  cname: [{ required: true, message: "请输入", trigger: "blur" }],
};
// 获取到的第一级指标范围基础数据集合
const dataTreeDefault = ref([]);
// 是否是输入触发
const isInput = ref(false);
// 当前操作的表格下标
const activeIndex = ref(-1);
// 指标输入框元素集合
const inputRef = ref([]);
// 下拉数据处理
const dataTree = computed(() => {
  return (index) => {
    const { firstOptions, input_indicator_tag, oldQuery } = state.form.warningScopeRows[index];
    let query = isInput.value ? input_indicator_tag : oldQuery;
    if (!query) return firstOptions;
    let arr = firstOptions.filter((e) => e.label.includes(query));
    if (arr == "") {
      state.form.warningScopeRows[index].lastOptions = [];
      state.form.warningScopeRows[index].indicator_scope = "";
    }
    return arr;
  };
});
// 监听父组件传过来的指标表达式
watch(
  () => props.indicator_expression,
  async (n) => {
    await nextTick();
    let tableCreateKeys = n?.match(/\$(.+?)\$/g) || [];
    let arr = [];
    tableCreateKeys.forEach((e) => {
      let i = state.form.warningScopeRows.findIndex((el) => el.key == e);
      if (i >= 0) {
        arr[i] = state.form.warningScopeRows[i];
      } else {
        arr.push({
          key: e,
          input_indicator_tag: "",
          indicator_scope: "",
          indicator_tag: "",
          oldQuery: "",
          firstOptions: dataTreeDefault.value,
          lastOptions: [],
          cname: "",
          visible: false,
          is_required: 1,
          is_linkage: 0,
        });
      }
    });
    state.form.warningScopeRows = arr;
  }
);
// 监听编辑的原数据，并显示
watch(
  () => props.warningScopeRows,
  (n) => {
    state.form.warningScopeRows =
      n?.map((e) => {
        return {
          key: e.key,
          input_indicator_tag: e.input_indicator_tag,
          indicator_scope: e.indicator_scope,
          indicator_tag: e.indicator_tag,
          firstOptions: dataTreeDefault.value,
          lastOptions: [],
          oldQuery: "",
          visible: false,
          cname: e.cname,
          is_required: e.is_required,
          is_linkage: e.is_linkage,
        };
      }) || [];
  },
  {
    deep: true,
    immediate: true,
  }
);
// 选择第一级，获取第二级数据
const chooseTreeFirst = (index, data) => {
  inputRef.value[index].focus();
  state.form.warningScopeRows[activeIndex.value].indicator_tag = "";
  state.form.warningScopeRows[index].indicator_scope = data.label;
  data.isLoading = true;
  state.form.warningScopeRows[index].lastOptions = [];
  const params = {
    label_name: data.label,
  };
  axios
    .get("/v1/api/prometheus", { params })
    .then((res) => {
      if (res.data.code == 200) {
        state.form.warningScopeRows[index].lastOptions = res.data.data?.list || [];
      } else {
        ElMessage.error(res.data.msg);
      }
    })
    .finally(() => {
      data.isLoading = false;
    });
};
// 获取第一级数据
const getDataTreeLevelFirst = () => {
  axios.get("/v1/api/prometheus").then((res) => {
    if (res.data.code == 200) {
      dataTreeDefault.value =
        res.data.data.list.map((e) => {
          return {
            label: e,
            isLoading: false,
          };
        }) || [];
    } else {
      ElMessage.error(res.data.msg);
    }
  });
};
let timer = null;
// 输入模糊查询数据
const inputLabel = (index, type) => {
  state.form.warningScopeRows[index].visible = true;
  activeIndex.value = index;
  isInput.value = type;
  if (state.form.warningScopeRows[index].input_indicator_tag == "") {
    state.form.warningScopeRows[index].lastOptions = [];
  }

  //   用户输入节流
  timer && clearTimeout(timer);
  timer = setTimeout(() => {
    if (type) {
      state.form.warningScopeRows[index].oldQuery = state.form.warningScopeRows[index].input_indicator_tag;
      state.form.warningScopeRows[index].indicator_scope = "";
      state.form.warningScopeRows[index].indicator_tag = "";
      state.form.warningScopeRows[index].lastOptions = [];
    }
  }, 200);
};
// 失去焦点是隐藏popper
const blurInput = (index) => {
  state.form.warningScopeRows[index].visible = false;
};
// 选择范围中的属性
const chooseTreeLast = (last, index, type) => {
  isInput.value = type;
  state.form.warningScopeRows[activeIndex.value].input_indicator_tag = last;
  state.form.warningScopeRows[activeIndex.value].indicator_tag = last;
};
// form表单元素
const form_ref = ref(null);
// 提交操作调用
const Submit = async () => {
  let form_valid = await new Promise((resolve, reject) => {
    form_ref.value.validate((res) => resolve(res));
  });
  let isFull = true;
  try {
    state.form.warningScopeRows.forEach((e, i) => {
      if (e.indicator_scope == "" || e.indicator_tag == "") {
        throw new Error(`第${i}条数据的指标没有选择！`);
      }
    });
  } catch (e) {
    if (e) {
      ElMessage.error(e);
      isFull = false;
    }
  }
  return form_valid && isFull;
};
// 获取第一级指标范围列表
onMounted(() => {
  getDataTreeLevelFirst();
});
defineExpose({
  Submit,
  form: state.form,
  form_ref,
});
</script>
<style lang="scss" scoped>
.indictor-tag {
  width: 100%;
}
</style>
<style lang="scss">
.cascader-operation {
  width: auto !important;
  padding: 0 !important;
  min-width: 180px !important;
  position: relative;
  min-height: 204px;
  .el-scrollbar {
    border-radius: 0;
  }
  .filter-first-tree-lists {
    height: 240px;
    display: flex;
    ul {
      min-width: 180px;
      height: 100%;
      &:not(:first-child) {
        border-left: 1px solid #ddd;
      }
      li {
        padding-left: 20px;
        line-height: 34px;
        max-width: 400px;
        word-break: break-all;
        transition: all 300ms;
        &:hover {
          background-color: #f1f1f1;
        }
        cursor: pointer;
        &.active {
          font-weight: bold;
          background-color: #f1f1f1;
        }
      }
    }
    .first-label-main {
      padding-right: 48px;
      position: relative;
      .tree-label {
        width: 100%;
      }
      .tree-icon {
        width: 40px;
        height: 100%;
        position: absolute;
        right: 0;
        top: 0;
        display: flex;
        align-items: center;
        svg {
          width: 20px;
        }
        .is-loading {
          animation: rotate 3s linear infinite;
          opacity: 0;
          &.loading-show {
            opacity: 1;
          }
        }
        @keyframes rotate {
          from {
            transform: rotate(0deg);
          }
          to {
            transform: rotate(360deg);
          }
        }
      }
    }
    .no-data {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: gray;
      box-sizing: border-box;
      padding: 0 20px;
    }
  }
}
</style>
