<template>
  <BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="500px" @ok="handleSubmit">
    <a-spin :spinning="loading">
      <BasicForm @register="registerForm">
        <template #menu="{ model, field }">
          <BasicTree
            v-model:value="model[field]"
            :treeData="treeData"
            :fieldNames="{ key: 'id', value: 'id' }"
            :checkedKeys="checkedKeys"
            checkable
            toolbar
            title="菜单分配"
            @check="onChecked"
          />
        </template>
      </BasicForm>
    </a-spin>
  </BasicDrawer>
</template>
<script lang="ts">
  import { defineComponent, ref, computed, unref, reactive } from 'vue';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  import { BasicTree } from '/@/components/Tree';
  import { allHierarchy2tree } from '/@/utils';
  import * as AuthorityApi from '/@/api/system/authorityApi';
  import * as RoleApi from '/@/api/system/roleApi';

  export default defineComponent({
    name: 'AuthDrawer',
    components: { BasicDrawer, BasicForm, BasicTree },
    emits: ['success', 'register'],
    setup(_, { emit }) {
      const isUpdate = ref(true);
      const treeData = ref([]);
      const entityId = ref(0);
      const halfKeys = ref([]);
      const checkedKeys = ref([]);

      const checkName = ref('');

      const loading = ref(true);

      const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
        labelWidth: 90,
        schemas: [
          {
            label: ' ',
            field: 'menu',
            slot: 'menu',
            component: 'Input',
          },
        ],
        showActionButtonGroup: false,
      });

      const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
        await resetFields();
        setDrawerProps({ confirmLoading: false });
        entityId.value = data?.record?.id;
        // 需要在setFieldsValue之前先填充treeData，否则Tree组件可能会报key not exist警告
        if (unref(treeData).length === 0) {
          treeData.value = (await AuthorityApi.all({ authorityId: 0 })) as any;
        }
        isUpdate.value = !!data?.isUpdate;
        let result: any = undefined;

        result = (await RoleApi.getById(entityId.value)) as any;
        loading.value = false;

        checkName.value = result.name;

        const halfArr = [] as any;
        const keyArr = [] as any;
        if (result.authorityList.length) {
          const roleAuthTree = allHierarchy2tree(result.authorityList, 'authorityId');
          const collectChildren = (auth: any) => {
            if (auth.children && auth.children.length > 0) {
              halfArr.push(auth.id);
              auth.children.forEach(collectChildren);
            } else {
              keyArr.push(auth.id);
            }
          };
          roleAuthTree.forEach(collectChildren);
          checkedKeys.value = keyArr;
          halfKeys.value = halfArr;
        }
        if (unref(isUpdate)) {
          await setFieldsValue({
            ...data.record,
          });
        }
      });

      const getTitle = computed(() => (!unref(isUpdate) ? '菜单分配' : '菜单分配'));
      const checkedMenuName = reactive([]);
      const getCheckedMenuName = (id: any, tree: any) => {
        for (let j = 0; j < tree.length; j++) {
          if (id === tree[j].id) {
            checkedMenuName.push(tree[j].title);
          } else {
            if (tree[j].children.length > 0) {
              getCheckedMenuName(id, tree[j].children);
            }
          }
        }
      };
      async function handleSubmit() {
        try {
          checkedMenuName.length = 0;
          const values = await validate();
          setDrawerProps({ confirmLoading: true });
          const authorities = [...values.menu, ...halfKeys.value];
          const data = authorities.map((item) => ({ id: item }));
          values.menu.map((item) => {
            getCheckedMenuName(item, treeData.value);
          });
          checkedMenuName.join(', ');

          await RoleApi.updateAuthority({ id: entityId.value, authorityList: data });

          closeDrawer();
          emit('success');
        } finally {
          setDrawerProps({ confirmLoading: false });
        }
      }

      const onChecked = (checkedKeys, { halfCheckedKeys }) => {
        halfKeys.value = halfCheckedKeys;
      };

      return {
        loading,
        registerDrawer,
        registerForm,
        getTitle,
        handleSubmit,
        treeData,
        checkedKeys,
        onChecked,
      };
    },
  });
</script>
