<template>
  <div class="wrap-select-box" @click="clickData">
    <a-tree-select
      :class="[style && Object.keys(style).length > 0 ? 'customStyle' : '']"
      v-if="props.treeConfig.isMultiple"
      v-model:value="checkedKeys"
      show-search
      :dropdown-style="{ maxWidth: '400px', maxHeight: '400px', overflow: 'auto' }"
      :dropdownMatchSelectWidth="300"
      :placeholder="placeholder"
      :allow-clear="false"
      :multiple="true"
      tree-default-expand-all
      :tree-data="treeState.treeData"
      tree-node-filter-prop="label"
      :field-names="{
        children: 'children',
        label: 'label',
        value: 'key',
      }"
      :disabled="disabled"
      :showCheckedStrategy="TreeSelect.SHOW_ALL"
      @blur="blurData"
      @change="(_, option) => changeSelectIds(checkedKeys, option)"
    />
    <a-tree-select
      :class="[style && Object.keys(style).length > 0 ? 'customStyle' : '']"
      v-else
      v-model:value="selectedKeys"
      show-search
      :dropdown-style="{ maxWidth: '400px', maxHeight: '400px', overflow: 'auto' }"
      :dropdownMatchSelectWidth="300"
      :placeholder="placeholder"
      :allow-clear="false"
      :multiple="false"
      tree-default-expand-all
      :tree-data="treeState.treeData"
      tree-node-filter-prop="label"
      :field-names="{
        children: 'children',
        label: 'label',
        value: 'key',
      }"
      :showCheckedStrategy="TreeSelect.SHOW_ALL"
      @blur="blurData"
      @change="changeSelectId"
    />
  </div>
</template>
<script lang="ts" setup>
  import { onMounted, watch, ref, reactive, computed, inject } from 'vue';
  import { TreeProps, TreeSelect } from 'ant-design-vue';
  import { getInfo } from '/@/api/system/generator/treeStructure';
  import { TreeStructureType } from '/@/enums/treeStructure';
  import { apiConfigFunc, isValidJSON } from '/@/utils/event/design';
  import { cloneDeep } from 'lodash-es';
  import { ApiItem } from '/@/model/generator/treeStructure';
  const formModel = inject<any>('formModel', null);
  const isCustomForm = inject<boolean>('isCustomForm', false);
  const props = defineProps({
    value: String,
    defaultValue: String,
    disabled: Boolean,
    codeType: String,
    treeConfig: {
      default: () => {
        return {};
      },
      type: Object,
    },
    placeholder: {
      default: '请选择',
      type: String,
    },
    style: Object,
  });
  const emit = defineEmits(['update:value', 'change', 'blur', 'click']);
  const selectedKeys = ref<string>();
  const checkedKeys = ref<string[] | number[]>([]);
  const treeState = reactive({
    treeData: [] as TreeProps['treeData'],
    height: 600,
    treeDataMap: new Map(),
  });
  watch(
    () => props.treeConfig.id,
    async (_val) => {
      if (_val) {
        resetData();
        await getTreeData();
      }
    },
  );
  watch(
    () => props.treeConfig.isMultiple,
    async (_val) => {
      if (_val) resetData();
    },
  );
  watch(
    () => props.value,
    () => {
      initData();
      emit('change', props.value);
    },
  );
  // watch(checkedKeys, () => {
  //   changeSelectIds(checkedKeys.value);
  // });
  // watch(selectedKeys, () => {
  //   changeSelectIds(selectedKeys.value);
  // });
  onMounted(async () => {
    await getTreeData();
    initData();
  });
  function resetData() {
    if (props.treeConfig.isMultiple) {
      checkedKeys.value = [];
      changeSelectIds(checkedKeys.value);
    } else {
      selectedKeys.value = '';
      changeSelectIds(selectedKeys.value);
    }
  }
  function initData() {
    if (props.value) {
      if (props.treeConfig.isMultiple) {
        let val = props.value.split(',');
        checkedKeys.value = val;
      } else {
        selectedKeys.value = props.value;
      }
    } else if (props.defaultValue) {
      if (props.treeConfig.isMultiple) {
        let val = props.defaultValue.split(',');
        checkedKeys.value = val;
      } else {
        selectedKeys.value = props.defaultValue;
      }
    } else {
      checkedKeys.value = [];
      selectedKeys.value = '';
    }
  }
  async function getTreeData() {
    if (!props.treeConfig?.id) {
      return;
    }
    let formState = await getInfo(props.treeConfig?.id);
    let config = JSON.parse(formState.config);
    if (formState.type == TreeStructureType.STATIC) {
      // treeState.treeData = config.staticData;
      let data: Array<ApiItem> = [];
      config.staticData.forEach((element, index) => {
        let res = getItem(element, index, element.value);
        data.push(res);
      });
      treeState.treeData = data;
    } else {
      let data: Array<ApiItem> = [];

      config.apiData.apiConfig.apiParams = [
        { key: '1', title: 'Query Params', tableInfo: [] },
        { key: '2', title: 'Header', tableInfo: [] },
        { key: '3', title: 'Body', tableInfo: [] },
      ];
      if (config.apiData.apiConfig.requestParamsConfigs) {
        let temp: any = [];
        config.apiData.apiConfig.requestParamsConfigs.forEach((item) => {
          transferData(temp, item, 'requestParamsConfigs');
        });
        config.apiData.apiConfig.apiParams[0].tableInfo = temp;
      }
      if (config.apiData.apiConfig.requestHeaderConfigs) {
        let temp: any = [];
        config.apiData.apiConfig.requestHeaderConfigs.forEach((item) => {
          transferData(temp, item, 'requestHeaderConfigs');
        });
        config.apiData.apiConfig.apiParams[1].tableInfo = temp;
      }
      if (config.apiData.apiConfig.requestBodyConfigs) {
        let temp: any = [];
        config.apiData.apiConfig.requestBodyConfigs.forEach((item) => {
          transferData(temp, item, 'requestBodyConfigs');
        });
        config.apiData.apiConfig.apiParams[2].tableInfo = temp;
      }
      let apiData = await apiConfigFunc(config.apiData.apiConfig, !isCustomForm, formModel);
      let labelKey = config.apiData.apiColumns[0].dataIndex;
      let valueKey = config.apiData.apiColumns[1].dataIndex;
      if (apiData && apiData.data && Array.isArray(apiData.data) && apiData.data.length > 0) {
        apiData.data.forEach((element) => {
          let res = getApiItem(element, labelKey, valueKey, element[valueKey]);
          data.push(res);
        });
      }
      treeState.treeData = data;
    }
    setTreeDataMap(cloneDeep(treeState.treeData));
  }
  function transferData(temp, item, key) {
    if (item.assignmentType == 'value') {
      let obj = props.treeConfig?.innerParams.find((k) => k.key == key && k.name == item.name);
      let val = '';
      if (obj) {
        let value = isValidJSON(obj.bindComp);
        val = JSON.stringify({ bindField: value.field, fieldKey: value.key });
      }
      temp.push({
        bindType: 'data',
        dataType: item.dataType,
        name: item.name,
        type: null,
        value: val,
      });
    } else if (item.assignmentType == 'currentInfo') {
      temp.push({
        bindType: 'data',
        dataType: item.dataType,
        name: item.name,
        type: null,
        value: item.config,
      });
    }
  }
  function getApiItem(item, labelKey, valueKey, value): ApiItem {
    let childrenArr: Array<ApiItem> = [];
    if (item.children?.length > 0) {
      item.children.forEach((element) => {
        let value2 = props.treeConfig?.isSaveLast
          ? element[valueKey]
          : value + '---' + element[valueKey];
        childrenArr.push(getApiItem(element, labelKey, valueKey, value2));
      });
    }
    // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
    let { children, ...otherParams } = item;
    return {
      ...otherParams,
      label: item[labelKey],
      key: value,
      children: childrenArr,
    };
  }
  function getItem(item, index, rowKey): ApiItem {
    let childrenArr: Array<ApiItem> = [];
    if (item.children?.length > 0) {
      item.children.forEach((element, index2) => {
        let key = index + '---' + index2;
        let rowKey2 = props.treeConfig?.isSaveLast ? element.value : rowKey + '---' + element.value;
        childrenArr.push(getItem(element, key, rowKey2));
      });
    }
    // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
    let { children, ...otherParams } = item;
    return {
      ...otherParams,
      label: item.label,
      index: index,
      key: rowKey,
      children: childrenArr,
    };
  }
  function setTreeDataMap(treeData) {
    if (treeData) {
      treeData.forEach((element) => {
        setTreeMapItem(element);
      });
    }
  }
  function setTreeMapItem(item) {
    if (item.children.length > 0) {
      item.children.forEach((element) => {
        setTreeMapItem(element);
      });
    }
    // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
    let { children, ...otherParams } = item;
    treeState.treeDataMap.set(item.key, otherParams);
  }
  function changeSelectIds(ids, options?) {
    let val = '';
    if (props.treeConfig.isMultiple) {
      val = ids.join(',');
    } else {
      val = ids;
    }
    emit('update:value', val);
    emit('change', val, options);
  }
  function changeSelectId(val, options) {
    emit('update:value', val);
    emit('change', val, options);
  }
  function blurData() {
    emit('blur');
  }
  function clickData() {
    emit('click');
  }
  const border = computed(() => {
    return props.style?.border || '1px solid #d9d9d9';
  });
</script>
<style lang="less" scoped>
  .wrap-select-box {
    width: 100%;
    display: flex;
  }

  .customStyle {
    :deep(.ant-select-selector) {
      border: v-bind(border);
    }
  }
</style>
