<script setup>
import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
import { reactive, ref, watch, defineExpose, nextTick } from 'vue'
import { executeStrFunction } from '@vue2-client/utils/runEvalFunction'
import debounce from 'lodash.debounce'

const config = reactive({})
// 暂存选中的数据
const expandedKeys = ref([])
// 是否加载中
const spinning = ref(false)
// 选中的 key
const checkedKeys = ref([])
// 定义 tree 数据
const _treeData = ref([])
// 存储搜索结果的树数据
const filteredTreeData = ref([])
// 定义最深一层的 数据
const deepestNodes = ref([])
// 定义激活的按钮
const activeButtonIndex = ref({})
// 是否全选
const checkall = ref(false)
// 选了但没有全选
const indeterminate = ref(false)
// 替换字段
let _replaceFields = reactive({ children: 'children', title: 'title', key: 'key' })
// 暂存查询信息
const searchInfo = ref({})
const props = defineProps({
  // 树数据
  // example: [{ title: '标题', key: '1', children: []}]
  treeData: {
    type: Array,
    required: false,
    default: () => []
  },
  configName: {
    type: String,
    required: false,
    default: undefined
  },
  env: {
    type: String,
    default: 'prod'
  },
  replaceFields: {
    type: Object,
    default: () => ({ children: 'children', title: 'title', key: 'key' })
  }
})
// maxHeight:config.search?'calc(100vh - 200px - 5.6rem)':
// 定义一个计算属性
function heightStore () {
  if (config.search) {
    if (config.tabBtn && config.tabBtn.length > 0) {
      return ['7rem', 'calc(100vh - 200px - 7.6rem)']
    } else {
      return ['5rem', 'calc(100vh - 200px - 5.6rem)']
    }
  } else {
    if (config.tabBtn && config.tabBtn.length > 0) {
      return ['5rem', 'calc(100vh - 200px - 5rem)']
    } else {
      return ['3rem', 'calc(100vh - 200px - 3rem)']
    }
  }
}

// 监听 checkbox 选中 的变化
watch(checkedKeys, (checkedKeys) => {
  // 筛选出最底层的数据 返回
  const deepNodes = []
  const deepKeys = []
  checkedKeys.forEach(key => {
    const node = deepestNodes.value.find(node => node[_replaceFields.key] === key)
    if (node) {
      deepNodes.push(node)
      deepKeys.push(node[_replaceFields.key])
    }
  })
  nextTick(() => {
    if (deepNodes.length === 0) {
      checkall.value = false
      indeterminate.value = false
    } else {
      indeterminate.value = !checkall.value
    }
  })
  emit('treeOnChecked', checkedKeys, deepNodes, deepKeys)
}, { immediate: true })
//
// watch(() => props.replaceFields, (newReplaceFields) => {
//   if (newReplaceFields) {
//     Object.assign(_replaceFields, newReplaceFields)
//   }
// }, { immediate: true })
// 如果有configName 要先获取配置
if (props.treeData && props.treeData.length > 0) {
  _treeData.value = props.treeData
  deepestNodes.value = getDeepestNodes(_treeData.value)
}
if (props.replaceFields) {
  _replaceFields = props.replaceFields
}
if (props.configName) {
  getConfigByName(props.configName, undefined, (x) => {
    Object.assign(config, x)
    Object.assign(_replaceFields, x.replaceFields)
    if (x.treeData.indexOf('logic@') >= 0) {
      // 如果数据源是 logic
      getData()
    }
  }, props.env === 'dev')
}

const emit = defineEmits(['onSelect'])

function onSelect (keys, e) {
  emit('onSelect', keys, e)
}

async function getData (param = {}) {
  spinning.value = true
  const currentUser = JSON.parse(localStorage.getItem(process.env.VUE_APP_USER_KEY))
  await runLogic(config.treeData.substring(6), Object.assign(param, {
    selectedId: this.$route.query.selected,
    orgId: currentUser.orgid,
    userId: currentUser.id,
    depId: currentUser.f_department_id
  }), config.serviceName, props.env === 'dev').then(res => {
    _treeData.value = res
    deepestNodes.value = getDeepestNodes(_treeData.value)
    spinning.value = false
  }).catch(e => {
    console.error('获取数据失败：' + e)
  })
}

function reLoad () {
  getData(searchInfo.value)
}

function nodeItemClick (e) {
  if (this.expandedKeys.includes(e.eventKey)) {
    this.expandedKeys = this.expandedKeys.filter(item => item !== e.eventKey)
  } else {
    this.expandedKeys.push(e.eventKey)
  }
}

const debouncedSearch = debounce((value) => {
  console.log('Search:', value)
  // 在这里执行你的搜索逻辑
  if (value) {
    filteredTreeData.value = searchInTree(_treeData.value, value)
  } else {
    filteredTreeData.value = []
  }
}, 233)

function onChange (e) {
  const searchInput = e.target.value
  debouncedSearch(searchInput)
}

function searchInTree (tree, keyword) {
  return tree.reduce((acc, node) => {
    if (node[_replaceFields.title].includes(keyword)) {
      acc.push(node)
    } else if (node[_replaceFields.children]) {
      const childResults = searchInTree(node[_replaceFields.children], keyword)
      if (childResults.length > 0) {
        acc.push({
          ...node,
          children: childResults
        })
      }
    }
    return acc
  }, [])
}

function action (record, func) {
  emit('action', record, record[_replaceFields.key], null, func)
}

function getDeepestNodes (treeData) {
  const deepestNodes = []

  function traverse (node) {
    if (!node[_replaceFields.children] || node[_replaceFields.children].length === 0) {
      deepestNodes.push(node)
    } else {
      node[_replaceFields.children].forEach(child => traverse(child))
    }
  }

  treeData.forEach(node => traverse(node))
  return deepestNodes
}

function onCheckAllChange (e) {
  checkedKeys.value = e.target.checked ? deepestNodes.value.map(node => node[_replaceFields.key]).filter(item => item !== 'noCatch') : []
  nextTick(() => {
    checkall.value = e.target.checked
    indeterminate.value = false
  })
}

async function btnFuncClick (index) {
  activeButtonIndex.value = Object.assign({}, activeButtonIndex.value, { [index]: !!!activeButtonIndex.value[index] })
  // 组织参数
  // 把activeButtonIndex.value groupType 相同的其他值改成 false
  Object.keys(activeButtonIndex.value).forEach((key) => {
    if (key != index && config.tabBtn[key].groupType === config.tabBtn[index].groupType) {
      activeButtonIndex.value[key] = false
    }
  })
  const param = {}
  // 循环执行已经激活的自定义方法
  Object.keys(activeButtonIndex.value).forEach((key) => {
    if (activeButtonIndex.value[key]) {
      const item = config.tabBtn[key]
      if (item.customFunction) {
       Object.assign(param, executeStrFunction(item.customFunction, [param]))
      }
    }
  })
  // 获取到 param 执行 getData
 await getData(param)
}

// 使用 defineExpose 暴露方法
defineExpose({
  reLoad
})

</script>

<template>
  <div id="XTreeWarp">
    <div class="tree_title" v-if="config.title">
      <a-row style="font-size: medium;line-height: 3rem">
        <a-col :offset="2">
          <span>{{ config.title }}</span>
        </a-col>
      </a-row>
      <a-row v-if="config.search">
        <div class="content-search">
          <a-checkbox
            class="checkbox"
            :indeterminate="indeterminate"
            :checked="checkall"
            @change="onCheckAllChange">
          </a-checkbox>
          &nbsp;
          <a-input
            placeholder="请输入搜索关键字"
            @change="onChange">
            <a-icon slot="prefix" type="search"/>
          </a-input>
        </div>
      </a-row>
    </div>
    <a-row v-if="config.tabBtn && config.tabBtn.length > 0">
      <div class="content-search" style="padding-top:7px;padding-left: 10px">
        <a-space>
          <a-button
            v-for="(item,index) in config.tabBtn"
            @click="btnFuncClick(index,item.customFunction)"
            :class="{ 'active-button': activeButtonIndex[index] }"
            :key="index">{{ item.name }}
          </a-button>
        </a-space>
      </div>
    </a-row>
    <div
      class="tree_main"
      :style="{
        maxHeight:heightStore()[1]
      }">
      <a-spin :spinning="spinning">
        <a-tree
          v-model="checkedKeys"
          :tree-data="filteredTreeData && filteredTreeData.length> 0?filteredTreeData: _treeData"
          :checkable="config.checkable"
          :blockNode="true"
          :replaceFields="_replaceFields"
          :expandedKeys.sync="expandedKeys"
          :default-selected-keys="_treeData && _treeData.length > 0 ? [_treeData[0][_replaceFields.key]] : null"
          :default-expand-all="true"
          @select="onSelect"
        >
          <template slot="title" slot-scope="item">
            <span @click="nodeItemClick(item)">
              <a-tooltip placement="right" :title="item[_replaceFields.title]">
                {{
                  item.dataRef[replaceFields.children] && item.dataRef[replaceFields.children].length > 0 ?
                    item[_replaceFields.title]
                    : config.deepNodeMaxWidth && item[_replaceFields.title].length > config.deepNodeMaxWidth ? item[_replaceFields.title].substring(0, config.deepNodeMaxWidth) + '...' : item[_replaceFields.title]
                }}{{ item.hasOwnProperty('count') ? ' (' + item.count + ')' : '' }}
              </a-tooltip>
            </span>
            <a-space style="float:right;margin-right: .2rem">
              <a-icon
                v-for="icon in config.btn"
                @click="action(item, icon.func)"
                :key="icon.func"
                v-if="executeStrFunction( icon.customFunction,[item])"
                :type="icon.icon"
                :style="{color:icon.color}"></a-icon>
            </a-space>
          </template>
        </a-tree>
      </a-spin>
    </div>
  </div>
</template>

<style lang="less" scoped>
.tree_title {
  background-color: #E0E5EB;
  border-radius: 8px 8px 0 0;

  .content-search {
    background-color: rgb(224, 229, 235);
    height: 2.6rem;
    padding: 0 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-top: 1px solid rgba(0, 0, 0, 0.05);
    margin: auto 0;
  }
}

.active-button {
  border-color: @primary-color !important;
  color: @primary-color !important;
}

.ant-btn:focus {
  color: rgba(0, 0, 0, 0.65);
  background-color: #fff;
  border-color: #d9d9d9
}

.tree_main {
  width: 100%;
  display: inline-block;
  overflow-y: auto;
  //:deep(.ant-tree-child-tree){
  //  .ant-space-item {
  //    display: none;
  //  }
  //
  //  &:hover {
  //    .ant-space-item {
  //      display: block;
  //    }
  //  }
  //}

  :deep(.ant-tree li .ant-tree-node-content-wrapper) {
    color: #000000e0;
  }

  :deep(.ant-tree-checkbox) {
    top: .5rem !important;
  }

  :deep(.ant-tree-node-content-wrapper ) {
    display: inline;
  }

  :deep(.ant-tree li span.ant-tree-switcher, .ant-tree li span.ant-tree-iconEle) {
    color: #0000004d;

    i {
      font-size: 16px !important;
      line-height: 40px;
    }
  }

  :deep(.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper::before, .ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper::before) {
    height: 40px;
    border-radius: 6px;
  }

  :deep(.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-node-content-wrapper::before) {
    background: #e6f7ff;
  }

  :deep(.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-node-content-wrapper::before) {
    background: #e6f7ff;
  }

  :deep(.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-switcher) {
    color: #0000004d;
  }

  :deep(.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper.ant-tree-node-selected, .ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper.ant-tree-node-selected) {
    color: #000000e0;
  }

  :deep(.ant-tree li .ant-tree-node-content-wrapper) {
    line-height: 40px;
    height: 40px;
  }

  :deep(.ant-tree li) {
    padding-left: 2px;
  }

  :deep(.ant-tree ul) {
    padding-left: 10px;
  }

  :deep(.ant-tree-icon__customize) {
    display: none;
  }
}
</style>
