<template>
  <a-card :class="$style.treewrap">
    <a-spin v-if="spinning" :spinning="spinning" :class="$style.spin" />
    <template v-else>
      <a-tree
        v-if="treeData.length > 0"
        :key="updateKey"
        :block-node="true"
        :tree-data="treeData"
        :selected-keys="selectedKeys"
        :default-expanded-keys="defaultExpandedKeys"
        :load-data="onLoadTreeData"
        @expand="onExpand"
        @select="onTreeSelect"
      >
        <template v-slot:title="{ key, title }">
          <div :class="$style.node">
            <div :title="title" :class="$style.text">
              {{ title }}
            </div>
            <!-- 编辑根节点 -->
            <div v-if="allowEdit && key === '-1'" :class="$style.action">
              <a-icon type="edit" title="编辑" @click.stop="editRoot" />
            </div>
          </div>
        </template>
      </a-tree>
      <a-empty v-else />

      <a-modal
        v-model="rootModifyVisible"
        title="编辑根节点"
        destroy-on-close
        v-bind="{ width: 800 }"
        :mask-closable="false"
        :confirm-loading="rootSaving"
        @ok="saveRoot"
        @cancel="$emit('closed')"
      >
        <sd-form ref="rootForm" :init-values="rootValues">
          <template>
            <sd-form-item name="name" />
          </template>
        </sd-form>
      </a-modal>
    </template>
  </a-card>
</template>

<script>
import { message } from 'ant-design-vue'
import storeMixin from '@/common/store-mixin'
import OrgService from './org-service'
import components from './_import-components/sd-org-tree-import'

export default {
  name: 'SdOrgTree',
  components,
  mixins: [storeMixin],
  props: {
    rootData: {
      type: Object,
      default: () => {},
    },
    editable: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      spinning: true,
      treeData: [],
      replaceFields: {
        title: 'text',
        key: 'id',
      },
      root: null,
      defaultExpandedKeys: [],
      selectedKeys: [],
      updateKey: 0,
      rootModifyVisible: false,
      rootValues: [
        {
          name: 'name',
          caption: '名称',
          dataType: 'string',
          required: true,
        },
      ],
      rootSaving: false,
    }
  },
  computed: {
    isSysAdmin() {
      return this.userInfo.roles.findIndex((role) => role.code === 'ADMINISTRATOR') > -1
    },
    allowEdit() {
      return this.editable && this.isSysAdmin
    },
  },
  created() {
    this.onLoadTreeData()
  },
  methods: {
    onExpand(expandedKeys, { expanded, node }) {
      if (!expanded) {
        const newKeys = expandedKeys.concat([])
        this.filterChild(node, newKeys)
        expandedKeys = newKeys
      }
      this.defaultExpandedKeys = expandedKeys
    },
    filterChild(node, keys) {
      if (node.dataRef?.children) {
        node.dataRef.children.forEach((item) => {
          const index = keys.indexOf(item.key)
          if (index > -1) {
            keys.splice(index, 1)
          }
          this.filterChild(item, keys)
        })
      }
      if (node.children) {
        node.children.forEach((item) => {
          const index = keys.indexOf(item.key)
          if (index > -1) {
            keys.splice(index, 1)
          }
          this.filterChild(item, keys)
        })
      }
    },
    onTreeSelect(key, e) {
      this.selectedKeys = [e.node.dataRef.key]
      this.$emit('treeSelect', {
        id: e.node.dataRef.key,
        text: e.node.dataRef.title,
      })
    },
    onLoadTreeData(treeNode) {
      return new Promise((resolve) => {
        const defaultExpandedKeys = this.defaultExpandedKeys.concat([])
        if (treeNode) {
          if (treeNode.dataRef.children) {
            resolve()
            return
          }
          OrgService.getOrgDepTree({ id: treeNode.dataRef.key }).then((deps) => {
            treeNode.dataRef.children = this.parseTreeData(deps.data, defaultExpandedKeys)
            this.treeData = [...this.treeData]
            this.spinning = false
            resolve()
          })
        } else {
          OrgService.getOrgDepRoot().then((deps) => {
            this.spinning = false
            if (deps.data?.length) {
              const oNodes = this.parseTreeData(deps.data, defaultExpandedKeys).map((item) => {
                return { ...item, checkable: false }
              })
              if (defaultExpandedKeys.length === 0) {
                this.treeData = oNodes
                if (this.defaultExpandedKeys.length === 0) {
                  this.defaultExpandedKeys = [this.treeData[0].key]
                }
                if (this.selectedKeys.length === 0) this.selectedKeys = [this.treeData[0].key]
                resolve()
              } else {
                this.loadExpand(oNodes, defaultExpandedKeys).then(() => {
                  this.treeData = oNodes
                  resolve()
                })
              }
            } else {
              resolve()
            }
          })
        }
      })
    },
    loadExpand(oNodes, defaultExpandedKeys) {
      // 默认加载并展开对应层的树
      return new Promise((resolve) => {
        Promise.all(
          oNodes
            .filter((oNode) => {
              return this.defaultExpandedKeys.indexOf(oNode.key) > -1
            })
            .map((oNode) => {
              return OrgService.getOrgDepTree({
                id: oNode.key,
              })
            })
        ).then((resAll) => {
          let childNodes = []
          resAll.forEach((res, index) => {
            oNodes.filter((oNode) => {
              return this.defaultExpandedKeys.indexOf(oNode.key) > -1
            })[index].children = this.parseTreeData(res.data, defaultExpandedKeys)
            childNodes = childNodes.concat(oNodes[index].children)
          })
          if (resAll.length !== 0) {
            if (defaultExpandedKeys.length !== 0) {
              this.loadExpand(childNodes, defaultExpandedKeys).then(() => {
                resolve()
              })
            } else {
              resolve()
            }
          }
        })
      })
    },
    parseTreeData(deps, expandedKeys) {
      return deps.map((dep) => {
        const index = expandedKeys.indexOf(dep.id)
        if (index > -1) {
          expandedKeys.splice(index, 1)
        }
        return {
          key: dep.id,
          title: dep?.props?.hierarchical === 'true' ? dep.text + '(已开启分级)' : dep.text,
          name: dep.text,
          isLeaf: dep.leaf,
          scopedSlots: {
            title: 'title',
          },
        }
      })
    },
    refresh() {
      this.onLoadTreeData().then(() => {
        this.updateKey++
      })
    },
    updateRoot(name) {
      this.treeData[0].title = name
    },
    editRoot() {
      this.rootValues[0].value = this.treeData[0].title
      this.rootModifyVisible = true
    },
    saveRoot() {
      this.rootSaving = true
      return new Promise((resolve) => {
        this.$refs.rootForm.validateFields().then((success) => {
          if (success) {
            const params = {}
            this.$refs.rootForm.getBackendValues().forEach((item) => {
              params[item.name] = item.value
            })

            return OrgService.saveDepRoot(params)
              .then((res) => {
                if (res.status === 200) {
                  message.success('保存成功')
                  resolve(true)
                } else {
                  message.error(res.data?.message || '保存失败')
                }
              })
              .catch(() => message.error('保存失败'))
              .finally(() => {})
          }
        })
      })
        .then((success) => {
          if (success) {
            this.updateRoot(this.$refs.rootForm.getFieldValue('name'))
            this.rootModifyVisible = false
          }
        })
        .finally(() => {
          this.rootSaving = false
        })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.spin {
  width: 100%;
  line-height: 10;
}
.treewrap {
  height: 100%;
  :global(.ant-input-search) {
    overflow: hidden;
  }
  :global(.ant-tree) {
    // height: calc(100% - 2 * #{$padding-md});
    height: 100%;
    overflow: auto;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  :global(.ant-card-body) {
    height: 100%;
    background: $white;
  }
  .active {
    color: $primary-color;
  }
  :global(.ant-tree.ant-tree-block-node li .ant-tree-node-content-wrapper) {
    width: auto;
  }
}
.node {
  display: flex;
  justify-content: space-between;
  .text {
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
</style>
