<script lang="ts" setup>
import type { TreeProps } from 'ant-design-vue';

import type { Recordable } from '@vben/types';

import type { RelationRequest } from '#/api/model';

import { onMounted, reactive, ref, unref } from 'vue';

import { useVbenDrawer } from '@vben/common-ui';

import { Button, message, Tree } from 'ant-design-vue';

import { MenuApi, RoleApi, TenantApi } from '#/api';
import { Icon } from '#/components/icon';
import { getLeafNodeIds } from '#/utils';

defineOptions({
  name: 'MenuGrant',
});
const emit = defineEmits(['success']);

const modelRef = ref<Recordable<any>>({});

const state = reactive<{
  checkedKeys: number[] | string[];
  expandedKeys: number[] | string[];
  lastLeafKeys: number[] | string[];
  selectedKeys: number[] | string[];
}>({
  selectedKeys: [],
  expandedKeys: [],
  checkedKeys: [],
  lastLeafKeys: [],
});

const treeData = ref<TreeProps['treeData']>([]);
const isExpand = ref(false);

// 所有节点key
const allNodeIds = ref([]);
// 当前展开的key
const currentExpandedKeys = ref([]);

const getRoleDetailData = async () => {
  const data =
    modelRef.value.type === 'tenant'
      ? await TenantApi.getMenuIds(unref(modelRef).id)
      : await RoleApi.getMenuIds(unref(modelRef).id);
  state.checkedKeys = data || [];
  state.expandedKeys = data || [];
  state.selectedKeys = data.filter((item: number | string) => {
    return state.lastLeafKeys.includes(item as never);
  });
};

const [Drawer, { close, setState, getData }] = useVbenDrawer({
  onConfirm: async () => {
    try {
      setState({ confirmLoading: true });
      const postData: RelationRequest = {
        id: unref(modelRef).id,
        relationIds: state.checkedKeys,
      };
      modelRef.value.type === 'tenant'
        ? await TenantApi.updateGrant(postData)
        : await RoleApi.updateGrant(postData);
      message.success('操作成功');
      close();
      emit('success');
    } catch {
      message.error('操作失败');
    } finally {
      setState({ confirmLoading: false });
    }
  },
  onOpenChange: async (isOpen: boolean) => {
    if (isOpen) {
      setState({ loading: true });
      const data = getData<Recordable<any>>();
      modelRef.value = { ...data.baseData };
      await getRoleDetailData();
      setState({ loading: false });
    }
  },
});

const fetch = async () => {
  treeData.value = (await MenuApi.getList(
    {},
  )) as unknown as TreeProps['treeData'];

  state.lastLeafKeys = getLeafNodeIds(unref(treeData));
};

onMounted(async () => {
  await fetch();
});
/**
 * 点击复选框触发处理
 * @param mCheckedKeys
 */
const handleCheck = (mCheckedKeys: any, e: any) => {
  state.selectedKeys = mCheckedKeys;
  state.checkedKeys = [...mCheckedKeys, ...e.halfCheckedKeys];
};

const handleExpand = (expandedKeys: any) => {
  state.expandedKeys = expandedKeys;
};
// 展开折叠按钮事件
const handleExpandAndCollapse = () => {
  isExpand.value = !isExpand.value;
  currentExpandedKeys.value = isExpand.value ? allNodeIds.value : [];
};
</script>
<template>
  <Drawer class="w-[1000px]" title="授权菜单">
    <Button type="primary" @click="handleExpandAndCollapse">
      {{ isExpand ? '折叠' : '展开' }}
    </Button>
    <Tree
      v-model:checked-keys="state.selectedKeys"
      :block-node="true"
      :checkable="true"
      :default-expand-all="true"
      :expanded-keys="state.expandedKeys"
      :field-names="{
        title: 'title',
        key: 'id',
      }"
      :tree-data="treeData"
      @check="handleCheck"
      @expand="handleExpand"
    >
      <template #title="{ meta }">
        <div class="flex items-center">
          <Icon v-if="meta.icon" :icon="meta.icon" class="mr-1" />
          <span>{{ meta.title }}</span>
        </div>
      </template>
    </Tree>
  </Drawer>
</template>
