<script lang="ts" setup>
import type { DataNode } from 'ant-design-vue/es/tree';

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

import type { RoleApi } from '#/api';

import { computed, ref } from 'vue';

import { useVbenDrawer, VbenTree } from '@vben/common-ui';
// import { IconifyIcon } from '@vben/icons';

import { Spin } from 'ant-design-vue';

import { useVbenForm } from '#/adapter/form';
import { createRole, queryMenuList, roleDetail, updateRole } from '#/api';
import { $t } from '#/locales';

import { useFormSchema } from '../data';

const emits = defineEmits(['success']);

const formData = ref<RoleApi.Role>();

const [Form, formApi] = useVbenForm({
  schema: useFormSchema(),
  showDefaultActions: false,
});

const menuIds = ref<DataNode[]>([]);
const loadingPermissions = ref(false);

const id = ref();
const [Drawer, drawerApi] = useVbenDrawer({
  async onConfirm() {
    const { valid } = await formApi.validate();
    if (!valid) return;
    const values = await formApi.getValues();
    // 过滤 menuIds 中的 null/undefined/false 值
    if (Array.isArray(values.menuIds)) {
      values.menuIds = values.menuIds.filter((id) => id !== null && id !== '');
    }
    drawerApi.lock();
    (id.value ? updateRole(id.value, values) : createRole(values))
      .then(() => {
        emits('success');
        drawerApi.close();
      })
      .catch(() => {
        drawerApi.unlock();
      });
  },
  async onOpenChange(isOpen) {
    if (isOpen) {
      const data = drawerApi.getData<RoleApi.Role>();
      await formApi.resetForm();
      if (data.id) {
        const roleDetailData = await roleDetail(data.id);
        formData.value = roleDetailData;

        // 提取 menus 中的 id 并赋值给 menuIds
        formData.value.menuIds = roleDetailData.menus.map((menu) => menu.id);

        id.value = data.id;
        formApi.setValues(roleDetailData);
      } else {
        id.value = undefined;
      }

      if (menuIds.value.length === 0) {
        await loadPermissions();
      }
    }
  },
});

function convertToTreeNode(item: any) {
  return {
    key: item.id,
    title: item.name,
    pid: item.pid || '',
    children: item.children?.map(convertToTreeNode) ?? null,
    meta: item.meta,
  };
}

async function loadPermissions() {
  loadingPermissions.value = true;
  try {
    const res = await queryMenuList('all');
    menuIds.value = res.map((item) => convertToTreeNode(item));
  } finally {
    loadingPermissions.value = false;
  }
}

const getDrawerTitle = computed(() => {
  return formData.value?.id
    ? $t('common.edit', '角色')
    : $t('common.create', '角色');
});

function getNodeClass(node: Recordable<any>) {
  const classes: string[] = [];
  if (node.value?.type === 'button') {
    classes.push('inline-flex');
    if (node.index % 3 >= 1) {
      classes.push('!pl-0');
    }
  }

  return classes.join(' ');
}
</script>
<template>
  <Drawer :title="getDrawerTitle">
    <Form>
      <template #menuIds="slotProps">
        <Spin :spinning="loadingPermissions" wrapper-class-name="w-full">
          <VbenTree
            :tree-data="menuIds"
            multiple
            bordered
            :default-expanded-level="2"
            :get-node-class="getNodeClass"
            v-bind="slotProps"
            value-field="key"
            label-field="meta.title"
            icon-field="meta.icon"
          >
            <template #node="{ value }">
              <!--              <IconifyIcon v-if="value.meta.icon" :icon="value.meta.icon" />-->
              {{ value.meta.locale }}
            </template>
          </VbenTree>
        </Spin>
      </template>
    </Form>
  </Drawer>
</template>
<style lang="css" scoped>
:deep(.ant-tree-title) {
  .tree-actions {
    display: none;
    margin-left: 20px;
  }
}

:deep(.ant-tree-title:hover) {
  .tree-actions {
    display: flex;
    flex: auto;
    justify-content: flex-end;
    margin-left: 20px;
  }
}
</style>
