<template>
  <div>
    <Breadcrumb :items="['系统设置', '域管理']" title="域管理" />
    <div class="container">
      <a-card class="general-card">
        <a-layout>
          <a-layout-sider :resize-directions="['right']">
            <a-divider style="margin-bottom: 0; margin-top: 0" />
            <div style="padding: 8px">
              <a-input-search
                v-model="keywordNode"
                placeholder="按区域名搜索"
                allow-clear
              />
            </div>
            <a-divider style="margin-bottom: 0; margin-top: 0" />
            <a-tree
              v-if="domainTree.length"
              ref="domainTreeRef"
              class="dtree"
              size="large"
              :field-names="{
                key: 'id',
                title: 'name'
              }"
              default-expand-all
              :data="treeData"
              :block-node="true"
              show-line
              @select="handleNodeClick"
            >
              <template #title="nodeData">
                <template v-if="getMatchIndex(nodeData?.title) < 0">{{
                  nodeData?.title
                }}</template>
                <span v-else>
                  {{
                    nodeData?.title?.substr(0, getMatchIndex(nodeData?.title))
                  }}
                  <span style="color: var(--color-primary-light-4)">
                    {{
                      nodeData?.title?.substr(
                        getMatchIndex(nodeData?.title),
                        keywordNode.length
                      )
                    }} </span
                  >{{
                    nodeData?.title?.substr(
                      getMatchIndex(nodeData?.title) + keywordNode.length
                    )
                  }}
                </span>
              </template>
              <template #extra="nodeData">
                <span v-show="selectNodeId === nodeData.id">
                  <a-dropdown trigger="hover">
                    <icon-apps
                      type="icon-more"
                      :size="16"
                      style="margin-right: 10px"
                    />
                    <template #content>
                      <a-doption @click="showDomainModal(0, nodeData)">
                        <template #icon>
                          <icon-plus-circle
                            style="color: rgb(var(--primary-6))"
                          />
                        </template>
                        <template #default>增加</template>
                      </a-doption>
                      <a-doption @click="showDomainModal(1, nodeData)">
                        <template #icon>
                          <icon-edit style="color: rgb(var(--success-6))" />
                        </template>
                        <template #default>修改</template>
                      </a-doption>
                      <a-doption @click="handleRemoveNode(nodeData)">
                        <template #icon>
                          <icon-minus-circle
                            style="color: rgb(var(--danger-6))"
                          />
                        </template>
                        <template #default>删除</template>
                      </a-doption>
                    </template>
                  </a-dropdown>
                  <!-- <IconApps style="font-size: 14px; color: #3370ff" /> -->
                </span>
              </template>
            </a-tree>
          </a-layout-sider>
          <a-layout-content>
            <a-card style="margin-top: 20px">
              <template #title>
                <div style="text-align: center">区域备注</div>
              </template>
              <a-textarea
                v-model="currentNode.memo"
                placeholder="区域描述"
                disabled
                :show-word-limit="true"
                :max-length="256"
                :auto-size="{
                  minRows: 25
                }"
              />
            </a-card>
          </a-layout-content>
        </a-layout>
      </a-card>
      <vModal
        v-model:visible="visibleModal"
        :title="modalTitle"
        @modal-handle-ok="domainHandleOk"
        @modal-handle-cancel="domainHandleCancel"
      >
        <div style="padding: 10px 15px">
          <a-form
            ref="domainFormRef"
            :model="domainForm"
            :auto-label-width="true"
            label-align="right"
            :rules="domainFormRules"
          >
            <a-form-item field="name" label="区域名称" show-colon>
              <a-input v-model="domainForm.name" placeholder="请输入区域名称" />
            </a-form-item>
            <a-form-item field="memo" label="区域备注" show-colon>
              <a-textarea
                v-model="domainForm.memo"
                placeholder="请输入区域备注"
                allow-clear
                :show-word-limit="true"
                :max-length="256"
                :auto-size="{
                  minRows: 5
                }"
              />
            </a-form-item>
          </a-form>
        </div>
      </vModal>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed, reactive, h, nextTick } from 'vue'
import {
  DomainTree,
  DomainTreeResParams,
  AddDomainResParams
} from '@/types/domain'
import {
  getDomainTree,
  addDomain,
  removeDomain,
  modifyDomain
} from '@/api/acs/domain'
import vModal from '@/components/modal/index.vue'
import { Modal, Message } from '@arco-design/web-vue'
import { FormInstance } from '@arco-design/web-vue/es/form'
import { removeNode, appendNode } from '@/utils'

const domainTreeRef = ref<any>() // 区域树ref
const modalType = ref(0) // 对话框类型，0：添加，1：修改
const domainFormRef = ref<FormInstance>()
const selectNodeId = ref(0) // 选中domain_id;

const currentNode = reactive({
  memo: ''
}) // 选中domain_id;
const keywordNode = ref('') // 筛选树节点关键字
const modalTitle = ref('添加区域') // 对话框标题
const visibleModal = ref(false) // 是否显示对话框
const domainTree = ref<DomainTree[]>([]) // 区域树
const domainForm = reactive<{
  id?: number
  name: string
  memo?: string
}>({
  id: undefined,
  name: '',
  memo: undefined
})

const domainFormRules = {
  name: [
    { required: true, message: '名称不能未空', trigger: 'blur' },
    {
      minLength: 2,
      maxLength: 20,
      message: '名称长度大于4个字节，且小于20个字节',
      validateTrigger: ['blur', 'change']
    }
  ]
}

/**
 * 区域树节点点击事件
 * @param newSelectkedKeys 已选择树节点key，数组。
 * @param data 选中树节点对应的data
 */
const handleNodeClick = (newSelectkedKeys: (string | number)[], data: any) => {
  const { node } = data
  selectNodeId.value = node.id
  currentNode.memo = node.memo!
}

/**
 * 递归获取ng-tree需要的结构体
 * @param domains 接口返回的树状数组
 */
const getNodesTree = (domains: DomainTree): DomainTree => {
  domains.key = domains.id.toString()
  domains.title = domains.name
  if (domains.children && domains.children.length > 0) {
    domains.children.map(res => getNodesTree(res))
  }
  return domains
}

// 根据查询库动态筛选树节点
const treeData = computed(() => {
  if (!keywordNode.value) return domainTree.value
  return filterTreeNode(keywordNode.value)
})

const filterTreeNode = (keyword: string) => {
  const loop = (data: DomainTree[]) => {
    const result: DomainTree[] = []
    data.forEach(item => {
      if (item.title.toLowerCase().indexOf(keyword.toLowerCase()) > -1) {
        result.push({ ...item })
      } else if (item.children) {
        const filterData = loop(item.children)
        if (filterData.length) {
          result.push({
            ...item,
            children: filterData
          })
        }
      }
    })
    return result
  }

  return loop(domainTree.value)
}

/**
 * 获取区域树
 */
const getTree = async () => {
  const { tree }: DomainTreeResParams = await getDomainTree()
  domainTree.value = tree.map(domains => {
    return getNodesTree(domains)
  })
}

/**
 * 根据title 获取tree节点 index
 * @param title node节点标题
 */
const getMatchIndex = (title: string) => {
  if (!keywordNode.value) return -1
  return title.toLowerCase().indexOf(keywordNode.value.toLowerCase()) as number
}

/**
 * 显示区域对话框
 * @param type 对话框类型
 * @param node 选中对话框节点data
 */
const showDomainModal = (type: number, node: DomainTree) => {
  const isAdd = type === 0
  modalType.value = type
  if (isAdd) {
    modalTitle.value = `在 ${node.name} 下添加区域`
    visibleModal.value = true
  } else {
    modalTitle.value = `修改 ${node.name} 区域信息`
    const { name, memo } = node
    visibleModal.value = true
    nextTick(() => {
      domainForm.name = name
      domainForm.memo = memo
    })
  }
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const domainHandleOk = async (cb: (closed: boolean) => void) => {
  const isValid = await domainFormRef.value?.validate()
  if (isValid) {
    return cb(false)
  }
  const isAdd = modalType.value === 0
  const pid = selectNodeId.value // 父节点
  const { name, memo } = domainForm
  try {
    if (isAdd) {
      const { id }: AddDomainResParams = await addDomain(pid, name, memo)
      const node: DomainTree = {
        id,
        key: id.toString(),
        name,
        title: name,
        memo,
        children: []
      }
      appendNode(domainTree.value, pid, node)
      Message.success('添加成功')
    } else {
      await modifyDomain(pid, name, memo)
      const node = domainTreeRef.value.getSelectedNodes()[0]
      node.title = name
      node.memo = memo
      currentNode.memo = memo!
      Message.success('修改成功')
    }
  } catch (e) {
    console.log('操起取消')
  }

  return cb(true)
}

const domainHandleCancel = () => {
  domainFormRef.value!.resetFields() // 初始化表单值
}

const handleRemoveNode = async (node: DomainTree) => {
  const { id, name } = node
  const title = {
    setup() {
      return () => h('strong', '警告')
    }
  }
  const ModalContent = {
    setup() {
      return () =>
        h('span', { style: 'margin-left: 10px;' }, [
          h('span', `确认删除 `),
          h('strong', `${name}`),
          h('span', ` 区域吗？`)
        ])
    }
  }
  Modal.warning({
    title: () => h(title),
    content: () => h(ModalContent),
    alignCenter: true,
    titleAlign: 'start',
    draggable: true,
    escToClose: true,
    width: 300,
    simple: true,
    hideCancel: false,
    onOk: async () => {
      try {
        await removeDomain(id)
        domainTree.value = removeNode(treeData.value, id)
        Message.success('删除成功')
      } catch (e) {
        console.log('操取消')
      }
    }
  })
}

onMounted(() => {
  try {
    getTree().then(() => console.log('获取区域树'))
  } catch (e) {
    console.log(e)
  }
})
</script>

<script lang="ts">
export default {
  name: 'Domain'
}
</script>

<style scoped lang="less">
.container {
  padding: 20px;
  min-height: 80vh;
  .dtree {
    padding: 10px 30px 0 20px;
    :deep(.arco-tree-node-selected) {
      background-color: rgb(var(--gray-2));
    }
    :deep(.arco-tree-node:hover) {
      background-color: rgb(var(--gray-2));
    }
    :deep(.arco-tree-node-title:hover) {
      background-color: transparent;
    }
  }
}
.container :deep(.arco-layout-sider) {
  width: 320px;
  margin-top: 20px;
  min-width: 326px;
  max-width: 100%;
  min-height: 77vh;
  ::-webkit-scrollbar {
    width: 12px;
    height: 4px;
  }
  ::-webkit-scrollbar-thumb {
    border: 4px solid transparent;
    background-clip: padding-box;
    border-radius: 7px;
    background-color: var(--color-text-4);
  }
}
</style>
