<template>
  <div>
    <Breadcrumb :items="['系统设置', '功能项管理']" title="功能项管理" />
    <div class="container">
      <a-card class="general-card" :bordered="false">
        <a-layout>
          <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="moduleTree.length"
                ref="moduleTreeRef"
                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="showModuleModal(0, nodeData)">
                          <template #icon>
                            <icon-plus-circle
                              style="color: rgb(var(--primary-6))"
                            />
                          </template>
                          <template #default>增加</template>
                        </a-doption>
                        <a-doption @click="showModuleModal(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"
                :body-style="{ padding: '0 5px' }"
                :bordered="false"
              >
                <!-- <template #extra>
        
              </template> -->
                <a-divider style="margin-bottom: 0; margin-top: 0" />
                <a-space direction="vertical" fill>
                  <div style="margin: 10px 10px 2px 10px; text-align: right">
                    <a-button type="primary" @click="showFuncModal(0)">
                      <template #icon>
                        <icon-plus />
                      </template>
                      <template #default>功能项</template>
                    </a-button>
                  </div>
                  <a-table
                    :columns="tableColumns"
                    :data="funList"
                    stripe
                    :hoverable="false"
                    table-layout-fixed
                  >
                    <template #check_auth="{ record }">
                      <a-tag v-if="record.check_auth" bordered color="green"
                        >是</a-tag
                      >
                      <a-tag v-else bordered color="gray">否</a-tag>
                    </template>
                    <template #optional="{ record }">
                      <a-space>
                        <a-button
                          type="primary"
                          status="success"
                          @click="showFuncModal(1, record)"
                        >
                          <template #icon>
                            <icon-edit />
                          </template>
                        </a-button>
                        <a-popconfirm
                          content="请先确认功能项是否被角色使用?"
                          type="warning"
                          @ok="handleRemoveFunc(record.id)"
                        >
                          <a-button type="primary" status="danger">
                            <template #icon>
                              <icon-delete />
                            </template>
                          </a-button>
                        </a-popconfirm>
                      </a-space>
                    </template>
                  </a-table>
                </a-space>
              </a-card>
            </a-layout-content>
          </a-layout>
        </a-layout>
      </a-card>
      <vModal
        v-model:visible="visibleModal"
        :title="modalTitle"
        @modal-handle-ok="moduleHandleOk"
        @modal-handle-cancel="moduleHandleCancel"
      >
        <div style="padding: 10px 15px">
          <a-form
            ref="moduleFormRef"
            :model="moduleForm"
            :auto-label-width="true"
            label-align="right"
            :rules="moduleFormRules"
          >
            <a-form-item field="tag" label="标记" show-colon>
              <a-input
                v-model="moduleForm.tag"
                placeholder="请输入模块标记"
                :disabled="modalType === 1"
              />
            </a-form-item>
            <a-form-item field="name" label="名称" show-colon>
              <a-input v-model="moduleForm.name" placeholder="请输入模块名称" />
            </a-form-item>
            <a-form-item field="memo" label="备注" show-colon>
              <a-textarea
                v-model="moduleForm.memo"
                placeholder="请输入模块备注"
                allow-clear
                :show-word-limit="true"
                :max-length="256"
                :auto-size="{
                  minRows: 5
                }"
              />
            </a-form-item>
          </a-form>
        </div>
      </vModal>
      <vModal
        v-model:visible="visibleFuncModal"
        :title="modalTitle"
        @modal-handle-ok="funcHandleOk"
        @modal-handle-cancel="funcHandleCancel"
      >
        <div style="padding: 10px 15px">
          <a-form
            ref="funcFormRef"
            :model="funcForm"
            :auto-label-width="true"
            label-align="right"
            :rules="funcFormRules"
          >
            <a-form-item field="tag" label="标记" show-colon>
              <a-input
                v-model="funcForm.tag"
                placeholder="请输入功能项标记"
                :disabled="modalType === 1"
              />
            </a-form-item>
            <a-form-item field="name" label="名称" show-colon>
              <a-input v-model="funcForm.name" placeholder="请输入功能项名称" />
            </a-form-item>
            <a-form-item field="isRead">
              <a-checkbox v-model="funcForm.checkAuth">
                访问时，是否需要验证权限
              </a-checkbox>
            </a-form-item>
          </a-form>
        </div>
      </vModal>
    </div>
  </div>
</template>

<script lang="ts" setup>
// 功能模块具体参数
import { ref, onMounted, computed, reactive, h, nextTick } from 'vue'
import {
  ModuleTree,
  ModuleTreeResParams,
  AddModuleResParams
} from '@/types/module'
import { Func, FuncListResParams, AddFuncResParams } from '@/types/function'
import {
  getModuleTree,
  addModule,
  removeModule,
  modifyModule
} from '@/api/acs/module'
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'
import {
  getFuncList,
  removeFunc,
  addFunc,
  modifyFunc
} from '@/api/acs/function'

const moduleTreeRef = ref<any>() // 模块树ref
const modalType = ref(0) // 对话框类型，0：添加，1：修改
const moduleFormRef = ref<FormInstance>()
const funcFormRef = ref<FormInstance>()
const selectNodeId = ref(0) // 选中domain_id;

const keywordNode = ref('') // 筛选树节点关键字
const modalTitle = ref('') // 对话框标题
const visibleModal = ref(false) // 是否显示对话框module
const visibleFuncModal = ref(false) // 是否显示对话框function
const moduleTree = ref<ModuleTree[]>([]) // 域树
const moduleForm = reactive<{
  id?: number
  name: string
  memo?: string
  tag: string
}>({
  id: undefined,
  name: '',
  memo: undefined,
  tag: ''
})
const funcForm = reactive<{
  moduleName?: string
  id?: number
  name: string
  tag: string
  checkAuth: boolean
}>({
  id: undefined,
  name: '',
  tag: '',
  checkAuth: false
})

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

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

const tableColumns = [
  {
    title: 'ID',
    dataIndex: 'id'
  },
  {
    title: '名称',
    dataIndex: 'name'
  },
  {
    title: '标记',
    dataIndex: 'tag'
  },
  {
    title: '鉴权',
    slotName: 'check_auth',
    dataIndex: 'check_auth'
  },
  {
    title: '操作',
    slotName: 'optional'
  }
]
const funList = ref<Func[]>([])

/**
 * 域树节点点击事件
 * @param newSelectkedKeys 已选择树节点key，数组。
 * @param data 选中树节点对应的data
 */
const handleNodeClick = async (
  newSelectkedKeys: (string | number)[],
  data: any
) => {
  const { node } = data
  selectNodeId.value = node.id
  funcForm.moduleName = node.name
  const { functions }: FuncListResParams = await getFuncList(node.id)
  funList.value = functions
}

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

// 根据查询库动态筛选树节点

const treeData = computed(() => {
  if (!keywordNode.value) return moduleTree.value
  return filterTreeNode(keywordNode.value)
})

const filterTreeNode = (keyword: string) => {
  const loop = (data: ModuleTree[]) => {
    const result: ModuleTree[] = []
    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(moduleTree.value)
}

/**
 * 获取域树
 */
const getTree = async () => {
  const { tree }: ModuleTreeResParams = await getModuleTree()
  moduleTree.value = tree.map(modules => {
    return getNodesTree(modules)
  })
}

/**
 * 根据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 showModuleModal = (type: number, node: ModuleTree) => {
  const isAdd = type === 0
  modalType.value = type
  if (isAdd) {
    modalTitle.value = `在 ${node.name} 下添加模块`
    visibleModal.value = true
  } else {
    modalTitle.value = `修改 ${node.name} 模块信息`
    const { name, memo, tag } = node
    visibleModal.value = true
    nextTick(() => {
      moduleForm.tag = tag
      moduleForm.name = name
      moduleForm.memo = memo
    })
  }
}

/**
 * 显示功能项modal
 * @param type modal类型
 * @param func
 */
const showFuncModal = (type: number, func?: Func) => {
  if (selectNodeId.value === 0) {
    Message.warning('请先选择对应功能模块')
    return
  }
  const isAdd = type === 0
  modalType.value = type
  if (isAdd) {
    modalTitle.value = `在 ${funcForm.moduleName} 下添加功能项`
    visibleFuncModal.value = true
  } else {
    modalTitle.value = `修改 ${func!.name} 功能项信息`
    const { name, tag } = func!
    visibleFuncModal.value = true
    nextTick(() => {
      funcForm.id = func!.id
      funcForm.tag = tag
      funcForm.name = name
      funcForm.checkAuth = func!.check_auth
    })
  }
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const moduleHandleOk = async (cb: (closed: boolean) => void) => {
  const isValid = await moduleFormRef.value?.validate()
  if (isValid) {
    return cb(false)
  }
  const isAdd = modalType.value === 0
  const pid = selectNodeId.value // 父节点
  const { name, memo, tag } = moduleForm
  try {
    if (isAdd) {
      const { id }: AddModuleResParams = await addModule(pid, name, tag, memo)
      const node: ModuleTree = {
        id,
        tag,
        key: id.toString(),
        name,
        title: name,
        memo,
        children: []
      }
      appendNode(moduleTree.value, pid, node)
      Message.success('添加成功')
    } else {
      await modifyModule(pid, name, memo)
      const node = moduleTreeRef.value.getSelectedNodes()[0]
      node.title = name
      node.tag = tag
      node.memo = memo
      Message.success('修改成功')
    }
  } catch (e) {
    console.error(e)
  }
  return cb(true)
}

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

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

/**
 * 删除模块节点
 */
const handleRemoveNode = async (node: ModuleTree) => {
  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 removeModule(id)
        moduleTree.value = removeNode(treeData.value, id)
        Message.success('删除成功')
      } catch (e) {
        console.error(e)
      }
    }
  })
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const funcHandleOk = async (cb: (closed: boolean) => void) => {
  const isValid = await funcFormRef.value?.validate()
  if (isValid) {
    return cb(false)
  }
  const isAdd = modalType.value === 0
  const pid = selectNodeId.value // 父节点
  const { id, name, tag, checkAuth } = funcForm
  try {
    if (isAdd) {
      const { id }: AddFuncResParams = await addFunc(pid, name, tag, checkAuth)
      funList.value.push({
        id,
        module_id: pid,
        name,
        tag,
        check_auth: checkAuth
      })
      Message.success('添加成功')
    } else {
      await modifyFunc(id!, name, checkAuth)
      const index = funList.value.findIndex(
        (item: Func) => item.id === funcForm.id
      )
      const item = funList.value[index]
      item.name = name
      item.check_auth = checkAuth
      Message.success('修改成功')
    }
  } catch (e) {
    console.error(e)
  }

  return cb(true)
}

/**
 * 删除功能
 * @param funId 功能项id
 */
const handleRemoveFunc = async (funId: number) => {
  try {
    await removeFunc(funId)
    const index = funList.value.findIndex((item: Func) => item.id === funId)
    funList.value.splice(index, 1)
    Message.success('删除成功')
  } catch (e) {
    console.error(e)
  }
}

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

<script lang="ts">
export default {
  name: 'Function'
}
</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>
