<template>
  <BasicModal
    wrapClassName="autherizeDialog"
    v-bind="$attrs"
    @register="registerRoleAuthModal"
    :title="t('APP功能授权')"
    destroy-on-close
    @ok="handleSubmit"
    width="90%"
  >
    <a-row class="h-full">
      <a-col :span="6">
        <NodeHead nodeName="系统功能" class="title" />
        <div class="treebox">
          <BasicTree
            :treeData="treeData"
            checkable
            ref="treeRef"
            @check="handleTreeSelect"
            :fieldNames="{ title: 'name', key: 'id' }"
          />
        </div>
      </a-col>
      <a-col :span="6">
        <NodeHead nodeName="按钮权限" class="title" />
        <div class="treebox">
          <BasicTree
            :treeData="buttonSelectData"
            checkable
            ref="ButtonRef"
            @check="handleButtonSelect"
            :fieldNames="{ title: 'name', key: 'id' }"
          />
        </div>
      </a-col>
      <a-col :span="6">
        <NodeHead nodeName="字段权限" class="title" />
        <div class="treebox">
          <BasicTree
            :treeData="columnSelectData"
            checkable
            ref="ColumnRef"
            @check="handleColumnSelect"
            :fieldNames="{ title: 'name', key: 'id' }"
          />
        </div>
      </a-col>
      <a-col :span="6">
        <NodeHead nodeName="表单权限" class="title" />
        <div class="treebox">
          <BasicTree
            :treeData="fieldSelectData"
            checkable
            ref="FieldRef"
            @check="handleFieldSelect"
            :fieldNames="{ title: 'name', key: 'id' }"
          />
        </div>
      </a-col>
    </a-row>
  </BasicModal>
</template>
<script lang="ts">
  import { defineComponent, ref, unref, nextTick } from 'vue';

  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { TreeItem, BasicTree, TreeActionType } from '/@/components/Tree';
  import { RoleSetAppAuth, getAppMenuAuth, getAppMenu } from '/@/api/system/role';
  import { useMessage } from '/@/hooks/web/useMessage';

  import {
    getAppMenuButtonList,
    getAppMenuColumnList,
    getAppMenuFieldList,
  } from '/@/api/system/menuButton';
  import { cloneDeep } from 'lodash-es';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { NodeHead } from '/@/components/ModalPanel/index';

  export default defineComponent({
    name: 'SelectUserModal',
    components: { BasicModal, BasicTree, NodeHead },
    emits: ['success', 'register'],
    setup(_, { emit }) {
      const { notification } = useMessage();
      const { t } = useI18n();
      const treeRef = ref<Nullable<TreeActionType>>(null);
      const ButtonRef = ref<Nullable<TreeActionType>>(null);
      const ColumnRef = ref<Nullable<TreeActionType>>(null);
      const FieldRef = ref<Nullable<TreeActionType>>(null);
      const treeData = ref<TreeItem[]>([]);
      const buttonData = ref<TreeItem[]>([]);
      const columnData = ref<TreeItem[]>([]);
      const fieldData = ref<TreeItem[]>([]);

      const buttonSelectData = ref<TreeItem[]>([]);
      const columnSelectData = ref<TreeItem[]>([]);
      const fieldSelectData = ref<TreeItem[]>([]);
      const btnKeys = ref<string[]>([]);
      const colKeys = ref<string[]>([]);
      const menuKeys = ref<string[]>([]);
      const fieldKeys = ref<string[]>([]);

      const btnFilterKeys = ref<string[]>([]);
      const colFilterKeys = ref<string[]>([]);
      const fieldFilterKeys = ref<string[]>([]);

      const rowId = ref('');

      function getTree(tree) {
        if (!tree) {
          return null;
        }
        return tree;
      }

      const [registerRoleAuthModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
        setModalProps({ confirmLoading: false });
        rowId.value = data.id;
        treeData.value = await getAppMenu();

        buttonData.value = await getAppMenuButtonList();
        columnData.value = await getAppMenuColumnList();
        fieldData.value = await getAppMenuFieldList();

        const authList = await getAppMenuAuth(rowId.value);
        menuKeys.value = authList.menuIds || [];
        btnKeys.value = authList.buttonIds || [];
        colKeys.value = authList.columnIds || [];
        fieldKeys.value = authList.formIds || [];
        let menuCheckedKey = [];
        let btnCheckedKey = [];
        let colCheckedKey = [];
        let fieldCheckedKey = [];
        menuKeys.value.forEach((o) => {
          getParentKeys(menuCheckedKey, treeData.value, o);
        });
        menuKeys.value = menuCheckedKey;
        getTree(unref(treeRef)).setCheckedKeys(authList.menuIds);
        initTree(menuCheckedKey);

        btnKeys.value.forEach((o) => {
          getParentKeys(btnCheckedKey, buttonSelectData.value, o);
        });
        btnKeys.value = btnCheckedKey;
        colKeys.value.forEach((o) => {
          getParentKeys(colCheckedKey, columnSelectData.value, o);
        });
        colKeys.value = colCheckedKey;

        fieldKeys.value.forEach((o) => {
          getParentKeys(fieldCheckedKey, fieldSelectData.value, o);
        });
        fieldKeys.value = fieldCheckedKey;

        nextTick(() => {
          getTree(unref(ButtonRef))?.setCheckedKeys(authList.buttonIds);
          getTree(unref(ColumnRef))?.setCheckedKeys(authList.columnIds);
          getTree(unref(FieldRef))?.setCheckedKeys(authList.formIds);
          getTree(unref(ButtonRef)).expandAll(true);
          getTree(unref(ColumnRef)).expandAll(true);
          getTree(unref(FieldRef)).expandAll(true);
        });

        getTree(unref(treeRef)).expandAll(true);
      });

      async function handleSubmit() {
        try {
          setModalProps({ confirmLoading: true });

          await RoleSetAppAuth({
            id: rowId.value,
            menuIds: menuKeys.value,
            buttonIds: btnKeys.value,
            columnIds: colKeys.value,
            formIds: fieldKeys.value,
          });
          notification.success({
            message: t('提示'),
            description: t('功能授权更新成功'),
          }); //提示消息
          closeModal();
          emit('success');
        } catch (error) {
          setModalProps({ confirmLoading: false });
        }
      }
      function handleButtonSelect(keys, e) {
        btnKeys.value = [...e.halfCheckedKeys, ...keys];
      }
      function handleColumnSelect(keys, e) {
        colKeys.value = [...e.halfCheckedKeys, ...keys];
      }
      function handleFieldSelect(keys, e) {
        fieldKeys.value = [...e.halfCheckedKeys, ...keys];
      }
      function handleTreeSelect(keys, e) {
        //keys  所有全选中的key
        //e.halfCheckedKeys  所有半选中的

        //如果没有半选  就证明全部全选  直接使用keys
        //如果有半选需要  使用keys + e.halfCheckedKeys

        const menuSelect: string[] = [...e.halfCheckedKeys, ...keys];

        initTree(menuSelect);

        menuKeys.value = menuSelect;
      }
      function initTree(menuSelect) {
        buttonSelectData.value = [];
        columnSelectData.value = [];
        fieldSelectData.value = [];

        btnFilterKeys.value = [];
        colFilterKeys.value = [];
        fieldFilterKeys.value = [];

        findMenuTree(buttonSelectData.value, treeData.value, menuSelect, 'button');
        findMenuTree(columnSelectData.value, treeData.value, menuSelect, 'column');
        findMenuTree(fieldSelectData.value, treeData.value, menuSelect, 'field');

        getTree(unref(ButtonRef))?.setExpandedKeys(menuSelect);
        getTree(unref(ColumnRef))?.setExpandedKeys(menuSelect);
        getTree(unref(FieldRef))?.setExpandedKeys(menuSelect);
      }
      function getParentKeys(checkedKey, arr, keys) {
        for (let i = 0; i < arr.length; i++) {
          let o = arr[i];
          if (o.id == keys) {
            checkedKey.push(o.id);
            if (o.categoryId > 0 && !checkedKey.includes(o.categoryId)) {
              checkedKey.push(o.categoryId);
            }
          }
          if (o.children?.length > 0) {
            getParentKeys(checkedKey, o.children, keys);
          }
        }
      }
      function findMenuTree(menuSelectTree, treeData, keys, type) {
        for (let i = 0; i < treeData.length; i++) {
          let o = cloneDeep(treeData[i]);
          if (keys.includes(o.id)) {
            o.children = [];
            menuSelectTree.push(o);
            if (treeData[i].children?.length > 0) {
              findMenuTree(o.children, treeData[i].children, keys, type);
            } else {
              let list =
                type == 'button'
                  ? buttonData.value
                  : type == 'column'
                  ? columnData.value
                  : fieldData.value;
              o.children = getAuthData(list, o.id, type);
            }
          }
        }
      }
      function getAuthData(list, id, type) {
        let arr: TreeItem[] = [];

        arr = list.filter((o) => {
          return o.menuId == id;
        });

        arr.forEach((o) => {
          o.categoryId = o.menuId;
          if (type == 'button') {
            btnFilterKeys.value.push(o.id);
          } else if (type == 'column') {
            colFilterKeys.value.push(o.id);
          } else {
            if (o.children && o.children.length > 0) {
              o.children?.forEach((k) => {
                fieldFilterKeys.value.push(k.id);
              });
            }
            fieldFilterKeys.value.push(o.id);
          }
        });
        return arr;
      }

      return {
        registerRoleAuthModal,
        handleSubmit,
        handleTreeSelect,
        handleButtonSelect,
        handleColumnSelect,
        handleFieldSelect,
        menuKeys,
        treeData,
        treeRef,
        ButtonRef,
        FieldRef,
        ColumnRef,
        buttonSelectData,
        columnSelectData,
        fieldSelectData,
        t,
      };
    },
  });
</script>
<style lang="less">
  .autherizeDialog {
    .ant-modal {
      top: 20px;
      height: calc(100% - 40px) !important;

      .ant-modal-content {
        height: 100%;

        .ant-modal-body {
          height: calc(100% - 102px) !important;

          .scrollbar__view {
            height: 100%;

            & > div {
              height: 100%;
              max-height: none !important;

              .ant-col {
                height: 100%;

                .treebox {
                  height: calc(100% - 50px);
                  overflow: auto;
                  padding-right: 15px;
                  margin-bottom: 10px;
                  border-right: solid 1px #ddd;

                  .vben-tree {
                    height: auto;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
</style>
<style lang="less" scoped>
  :deep(.ant-tree .ant-tree-switcher) {
    display: inline !important ;
  }

  :deep(.vben-tree__title) {
    padding-left: 0;
  }

  .title {
    height: 50px;
    padding-left: 20px;
    border-bottom: 1px solid #eee;
    border-right: 1px solid #ddd;
  }
</style>
