<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="{ row, $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="row.visible" popper-class="cascader-operation" placement="bottom-start">
                  <template #reference>
                    <el-input
                      v-model="state.form.warningScopeRows[$index].input_indicator_tag"
                      placeholder="请选择指标标签"
                      ref="inputRef"
                      @blur="blurInput($index)"
                      @focus="inputLabel($index, false)"
                      @input="inputLabel($index, true)"></el-input>
                  </template>
                  <div class="filter-first-tree-lists" @mousedown.prevent="">
                    <ul class="bg-scroll" ref="first_options_lists" v-show="row.firstOptions.length > 0">
                      <li
                        v-for="data in row.firstOptions"
                        :key="data"
                        :class="{
                          active: row.indicator_scope == data.label,
                        }">
                        <div class="first-label-main" @click="chooseTreeFirst($index, data)">
                          <div class="tree-label" v-html="data.label_html"></div>
                          <div class="tree-icon">
                            <bg-icon
                              style="font-size: 15px; color: #404a62"
                              class="is-loading"
                              :class="{ 'loading-show': data.isLoading }"
                              icon="#bg-ic-loading"></bg-icon>
                            <bg-icon style="font-size: 13px; color: #404a62" icon="#bg-ic-arrow-right"></bg-icon>
                          </div>
                        </div>
                      </li>
                    </ul>
                    <ul v-show="row.firstOptions.length == 0">
                      <li class="no-data">
                        {{
                          row.input_indicator_tag
                            ? row.firstOptionsLoading
                              ? "查询中"
                              : "未查询到相关指标范围数据"
                            : "请输入查询"
                        }}
                      </li>
                    </ul>
                    <ul class="bg-scroll" v-show="row.lastOptions?.length > 0">
                      <li
                        v-for="child in row.lastOptions"
                        :key="child"
                        @click="chooseTreeLast(child, $index, false)"
                        :class="{ active: row.indicator_tag == child }">
                        {{ child }}
                      </li>
                    </ul>
                    <ul v-show="row.indicator_scope && row.lastOptions?.length == 0">
                      <li class="no-data">
                        {{ row.lastOptionsLoading ? "查询中" : "未查询到相关指标标签" }}
                      </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";
import { delay } from "@/components/env";

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 first_options_lists = ref(null);
// 指标输入框元素集合
const inputRef = ref(null);
// 监听父组件传过来的指标表达式
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: "",
          firstOptionsLoading: false,
          firstOptions: [],
          lastOptionsLoading: false,
          lastOptions: [],
          cname: "",
          visible: false,
          is_required: 1,
          is_linkage: 0,
        });
      }
    });
    state.form.warningScopeRows = arr;
  }
);
// 选择第一级，获取第二级数据
const chooseTreeFirst = (index, data, isInfo = false) => {
  state.form.warningScopeRows[index].lastOptionsLoading = true;
  let i = "";
  // 是否是父组件传过来的默认展示数据
  if (!isInfo) {
    inputRef.value[index].focus();
    i = state.form.warningScopeRows[index].firstOptions.findIndex((e) => e.label == data.label);
    state.form.warningScopeRows[index].firstOptions[i].isLoading = true;
    state.form.warningScopeRows[index].indicator_tag = "";
    state.form.warningScopeRows[index].indicator_scope = data.label;
    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(() => {
      state.form.warningScopeRows[index].lastOptionsLoading = false;
      if (i === "") return;
      state.form.warningScopeRows[index].firstOptions[i].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 inputType = ref(false);
const TreeFilter = (index, type) => {
  let options = dataTreeDefault.value;
  const { input_indicator_tag, oldQuery } = state.form.warningScopeRows[index];
  state.form.warningScopeRows[index].firstOptions = [];
  // 如果没有输入，或者清空输入，则清除已选中的所有东西和所有下拉数据，并返回
  if (input_indicator_tag == "") {
    state.form.warningScopeRows[index].lastOptions = [];
    state.form.warningScopeRows[index].indicator_scope = "";
    state.form.warningScopeRows[index].indicator_tag = "";
    state.form.warningScopeRows[index].oldQuery = "";
    return;
  }
  // 如果只是聚焦，则使用旧的输入查询过滤，如果是输入，则使用输入的内容过滤
  let query = type ? input_indicator_tag : oldQuery;
  // 提升性能问题使用for循环遍历
  for (let i = 0; i < options.length; i++) {
    // 不符合直接跳出当次循环
    if (!options[i].label.includes(query)) continue;
    state.form.warningScopeRows[index].firstOptions.push({
      ...options[i],
      // 高亮显示和输入匹配的项
      label_html: options[i].label.replaceAll(
        input_indicator_tag,
        `<span class='mate-str'>${input_indicator_tag}</span>`
      ),
    });
  }
  // 如果第一级下拉没有数据，则隐藏第二级下拉，并清除当前现在的指标范围
  if (state.form.warningScopeRows[index].firstOptions.length == 0) {
    state.form.warningScopeRows[index].lastOptions = [];
    state.form.warningScopeRows[index].indicator_scope = "";
  }
  // 结束查询中
  state.form.warningScopeRows[index].firstOptionsLoading = false;
  // 查询后第一级滚动条滚动到顶部
  first_options_lists.value[index].scrollTop = 0;
};
// 输入模糊查询数据
const inputLabel = async (index, type) => {
  // 第一级显示查询中
  state.form.warningScopeRows[index].firstOptionsLoading = true;
  // 记录当前是聚焦还是输入
  inputType.value = type;
  // 用户输入节流
  if (timer) {
    clearTimeout(timer);
    timer = null;
  }
  timer = setTimeout(
    () => {
      state.form.warningScopeRows[index].visible = true;
      // 过滤下拉数据
      TreeFilter(index, type);
    },
    // 如果是聚集input的时候不需要节流，输入节流
    type ? 500 : 0
  );
};
// 失去焦点是隐藏popper
const blurInput = (index) => {
  const { input_indicator_tag, oldQuery } = state.form.warningScopeRows[index];
  // 判断是聚焦失去焦点还是输入后失去焦点，输入后失去焦点记录输入的内容，聚焦失去焦点还是使用之前的记录
  state.form.warningScopeRows[index].oldQuery = inputType.value ? input_indicator_tag : oldQuery;
  // 隐藏popper
  state.form.warningScopeRows[index].visible = false;
};
// 选择范围中的属性
const chooseTreeLast = async (last, index, type) => {
  isInput.value = type;
  inputRef.value[index].blur();
  state.form.warningScopeRows[index].input_indicator_tag = last;
  state.form.warningScopeRows[index].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 `第${i + 1}条数据的指标没有选择！`;
      }
    });
  } catch (e) {
    if (e) {
      ElMessage.error(e);
      isFull = false;
    }
  }
  return form_valid && isFull;
};
// 监听编辑的原数据，并显示
watch(
  () => props.warningScopeRows,
  (n) => {
    state.form.warningScopeRows =
      n?.map((e, i) => {
        chooseTreeFirst(i, { label: e.indicator_scope }, true);
        return {
          key: e.key,
          input_indicator_tag: e.indicator_tag,
          indicator_scope: e.indicator_scope,
          indicator_tag: e.indicator_tag,
          firstOptionsLoading: false,
          firstOptions: [],
          lastOptionsLoading: false,
          lastOptions: [],
          oldQuery: e.indicator_scope,
          visible: false,
          cname: e.cname,
          is_required: e.is_required,
          is_linkage: e.is_linkage,
        };
      }) || [];
  },
  {
    deep: true,
    immediate: true,
  }
);
// 获取第一级指标范围列表
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;
    min-width: 100%;
    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;
    }
  }
}
.mate-str {
  font-weight: bold;
}
</style>
