<script setup lang="tsx">
import { type DropdownOption, NButton, NDropdown, NPopconfirm, NSwitch, type TreeOption } from 'naive-ui';
import { ref, withDirectives } from 'vue';
import type { ModelCallback } from '@/hooks/common/form';
import { useAppStore } from '@/store/modules/app';
import { useDownLoadFile } from '@/hooks/common/download';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { fetchMenuTree, fetchRoleMenuTree } from '@/service/api/system/menu';
import {
  changeRoleStatus,
  dataScope,
  fetchAddRole,
  fetchDeleteRole,
  fetchEditRole,
  fetchGetRole,
  fetchGetRoleList,
  roleDeptTreeselect
} from '@/service/api/system/role';
import { $t } from '@/locales';
import hasPermission from '@/directive/permission/hasPermission';
import RoleAuthUserOperateModal from '@/views/system/role/modules/role-auth-user-operate-modal.vue';
import RoleAddUserOperateModal from '@/views/system/role/modules/role-add-user-operate-modal.vue';
import RoleOperateModel from './modules/role-operate-model.vue';
import RoleSearch from './modules/role-search.vue';
import RoleDataScopeOperateModal from './modules/role-data-scope-operate-modal.vue';

const appStore = useAppStore();
const { loading: exportLoading, downLoadExcelPost } = useDownLoadFile();

const optionsDropdown: DropdownOption[] = [
  { key: 'dataScope', label: '数据权限' },
  { key: 'authUser', label: '分配用户' }
];
// 数据权限
const roleId = ref<Api.SystemManage.Role['roleId']>('');
const drawerVisibleData = ref(false);
const deptOptions = ref<TreeOption[]>([]);
// 分配用户
const authUser = ref();
const drawerVisibleUser = ref(false);
// 添加用户
const drawerVisibleUserAdd = ref(false);

const {
  columns,
  columnChecks,
  data,
  loading,
  getData,
  getDataByPage,
  mobilePagination,
  searchParams,
  resetSearchParams
} = useTable({
  apiFn: fetchGetRoleList,
  apiParams: {
    pageNum: 1,
    pageSize: 10,
    // if you want to use the searchParams in Form, you need to define the following properties, and the value is null
    // the value can not be undefined, otherwise the property in Form will not be reactive
    status: null,
    roleName: null,
    roleKey: null
  },
  columns: () => [
    {
      type: 'selection',
      align: 'center',
      width: 48
    },
    {
      key: 'roleId',
      title: '角色编号',
      width: 200
    },
    {
      key: 'roleName',
      title: $t('page.manage.role.roleName'),
      minWidth: 120
    },
    {
      key: 'roleKey',
      title: '权限字符',
      minWidth: 120
    },
    {
      key: 'roleSort',
      title: '显示顺序',
      align: 'center',
      minWidth: 60
    },
    {
      key: 'status',
      title: $t('page.manage.role.roleStatus'),
      align: 'center',
      width: 150,
      render: row => {
        if (row.status === null || row.roleId === 1) {
          return null;
        }
        return (
          <NSwitch
            v-model:value={row.status}
            checked-value="0"
            unchecked-value="1"
            onUpdate:value={() => handleStatusChange(row)}
          />
        );
      }
    },
    {
      key: 'createTime',
      title: '创建时间',
      minWidth: 120
    },
    {
      key: 'operate',
      title: $t('common.operate'),
      align: 'center',
      width: 200,
      render: row => (
        <div class="flex-center gap-8px">
          {!row.admin && (
            <>
              {withDirectives(
                <NButton type="primary" ghost size="small" onClick={() => edit(row.roleId)}>
                  {$t('common.edit')}
                </NButton>,
                [[hasPermission, ['system:role:edit']]]
              )}
              {withDirectives(
                <div>
                  <NPopconfirm onPositiveClick={() => handleDelete(row.roleId)}>
                    {{
                      default: () => $t('common.confirmDelete'),
                      trigger: () => (
                        <NButton type="error" ghost size="small">
                          {$t('common.delete')}
                        </NButton>
                      )
                    }}
                  </NPopconfirm>
                </div>,
                [[hasPermission, ['system:role:remove']]]
              )}
              {withDirectives(
                <div>
                  <NDropdown trigger="hover" options={optionsDropdown} onSelect={key => handleDropdownSelect(key, row)}>
                    <NButton type="warning" ghost size="small">
                      更多
                    </NButton>
                  </NDropdown>
                </div>,
                [[hasPermission, ['system:role:edit']]]
              )}
            </>
          )}
        </div>
      )
    }
  ]
});

const {
  drawerVisible,
  operateType,
  editingData,
  handleAdd,
  handleEdit,
  checkedRowKeys,
  onBatchDeleted,
  onDeleted
  // closeDrawer
} = useTableOperate(data, getData);

// 菜单树
const menuOptions = ref<TreeOption[]>([]);

// 用户状态修改
function handleStatusChange(row: Api.SystemManage.Role) {
  const text = row.status === '0' ? '启用' : '停用';
  window.$dialog?.warning({
    title: '提示',
    content: `确定要${text}角色"${row.roleName}"吗？`,
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      return changeRoleStatus(row.roleId, row.status).then(res => {
        if (!res.error) {
          window.$message?.success(`${text}成功`);
        } else {
          row.status = row.status === '0' ? '1' : '0';
        }
      });
    },
    onNegativeClick: () => {
      row.status = row.status === '0' ? '1' : '0';
    },
    onClose: () => {
      row.status = row.status === '0' ? '1' : '0';
    },
    onEsc: () => {
      row.status = row.status === '0' ? '1' : '0';
    }
  });
}

// 批量删除
async function handleBatchDelete() {
  const { error } = await fetchDeleteRole(checkedRowKeys.value as string[]);
  if (!error) {
    await onBatchDeleted();
  }
}

async function handleDelete(id: Api.SystemManage.Role['roleId']) {
  const { error } = await fetchDeleteRole([id]);
  if (!error) {
    await onDeleted();
  }
}

async function edit(id: Api.SystemManage.Role['roleId']) {
  const { data: rowData, error } = await fetchGetRole(id);
  if (!error) {
    rowData.abilityIds = rowData.abilityIds === null ? [] : rowData.abilityIds;
    rowData.menuIds = rowData.menuIds === null ? [] : rowData.menuIds;
    editingData.value = rowData as Api.SystemManage.Role;
    handleEdit();
  }
}

/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect() {
  fetchRoleMenuTree(editingData.value?.roleId as string).then(res => {
    if (!res.error) {
      menuOptions.value = res.data!.menus;
      editingData.value!.menuIds = res.data!.checkedKeys;
    }
  });
}

/** 查询菜单树 */
function getMenuTree() {
  fetchMenuTree().then(res => {
    if (!res.error) {
      menuOptions.value = res.data as TreeOption[];
    }
  });
}

// 点击修改，弹窗打开时请求
function modelOpen(type: 'add' | 'edit') {
  if (type === 'edit') {
    getRoleMenuTreeselect();
  } else {
    getMenuTree();
  }
}

// 修改新增的提交
function handleSubmit(callback: (params: ModelCallback<Api.SystemManage.Role>) => void) {
  callback({
    add: fetchAddRole,
    edit: fetchEditRole,
    getData
  });
}

function handleDropdownSelect(key: string, row: Api.SystemManage.Role) {
  if (key === 'dataScope') {
    fetchGetRole(row.roleId).then(res => {
      if (!res.error) {
        editingData.value = res.data;
        drawerVisibleData.value = true;
      }
    });
  } else if (key === 'authUser') {
    roleId.value = row.roleId;
    drawerVisibleUser.value = true;
  }
}

// 根据角色ID查询部门树结构
function getRoleDeptTreeselect() {
  roleDeptTreeselect(editingData.value!.roleId).then(res => {
    if (!res.error) {
      deptOptions.value = res.data.depts as TreeOption[];
      editingData.value!.deptIds = res.data.checkedKeys;
    }
  });
}

// 根据角色ID查询部门树结构
function modelDataScopeOpen(type: 'add' | 'edit') {
  if (type === 'edit') {
    getRoleDeptTreeselect();
  }
}

// 提交数据权限更新
function handleSubmitDataScope(callback: (params: ModelCallback<Api.SystemManage.Role>) => void) {
  callback({
    edit: dataScope,
    getData
  });
}

// 选择用户授权成功后
function getAuthUser() {
  authUser.value.getList();
}

// 导出
function handleExport() {
  downLoadExcelPost('/system/role/export', searchParams);
}
</script>

<template>
  <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
    <RoleSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage" />
    <NCard :title="$t('page.manage.role.title')" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
      <template #header-extra>
        <TableHeaderOperation
          v-model:columns="columnChecks"
          :disabled-delete="checkedRowKeys.length === 0"
          :loading="loading"
          :has-perm="['system:role:add', 'system:role:remove']"
          @add="handleAdd"
          @delete="handleBatchDelete"
          @refresh="getData"
        >
          <template #middle>
            <NButton
              v-hasPermission="['system:role:export']"
              :loading="exportLoading"
              type="success"
              ghost
              size="small"
              @click="handleExport"
            >
              <template #icon>
                <SvgIcon icon="mdi:file-export-outline"></SvgIcon>
              </template>
              导出
            </NButton>
          </template>
        </TableHeaderOperation>
      </template>
      <NDataTable
        v-model:checked-row-keys="checkedRowKeys"
        :columns="columns"
        :data="data"
        size="small"
        :flex-height="!appStore.isMobile"
        :scroll-x="702"
        :loading="loading"
        remote
        :row-key="(row: Api.SystemManage.Role) => row.roleId"
        :pagination="mobilePagination"
        class="sm:h-full"
      />
      <!--添加修改角色-->
      <RoleOperateModel
        v-model:visible="drawerVisible"
        :operate-type="operateType"
        :row-data="editingData"
        :menu-options="menuOptions"
        @open="modelOpen"
        @submit="handleSubmit"
      />
      <!--数据权限-->
      <RoleDataScopeOperateModal
        v-model:visible="drawerVisibleData"
        operate-type="edit"
        :row-data="editingData"
        :dept-options="deptOptions"
        @open="modelDataScopeOpen"
        @submit="handleSubmitDataScope"
      />
      <!--分配用户-->
      <RoleAuthUserOperateModal
        ref="authUser"
        v-model:visible="drawerVisibleUser"
        :role-id="roleId"
        @add-user="drawerVisibleUserAdd = true"
      />
      <!--添加用户-->
      <RoleAddUserOperateModal v-model:visible="drawerVisibleUserAdd" :role-id="roleId" @ok="getAuthUser" />
    </NCard>
  </div>
</template>

<style scoped></style>
