<template>
  <div>
    <PlusPage
      ref="plusPageInstance"
      :columns="tableConfig"
      :request="getList"
      :before-search-submit="handleBeforeSearch"
      :is-card="true"
      :search="{
        labelWidth: 100,
        showNumber: 3
      }"
      :table="{
        actionBar: { buttons, type: 'link', width: 180, showNumber: 3 },
        adaptive: { offsetBottom: 50 },
        onSelectionChange: handleSelect,
        onFormChange: handleTableChange,
        onClickAction: handleTableOption
      }"
    >
      <template #table-title>
        <el-row class="button-row">
          <el-button
            v-perms="'system:role:add'"
            size="default"
            type="success"
            @click="handleCreate"
            >新增
          </el-button>
        </el-row>
      </template>
    </PlusPage>
    <!-- 弹窗编辑 -->
    <PlusDialogForm
      ref="dialogForm"
      v-model="form"
      v-model:visible="dialogVisible"
      :form="{
        columns,
        labelPosition: 'right',
        labelWidth: 100,
        rules,
        rowProps: { gutter: 20 },
        colProps: { span: 12 }
      }"
      :dialog="{ title: dialogTitle + '角色', width: 600, confirmLoading }"
      @confirm="handleSubmit"
      @change="handleFormChange"
      @submit-error="handleSubmitError"
      @close="handleClose"
      @opened="handleOpen"
    >
      <template #plus-field-menuIds>
        <menu-tree ref="menuRef" v-model="form.menuIds" />
      </template>
    </PlusDialogForm>

    <PlusDialogForm
      v-model="form"
      v-model:visible="dialogPermissionVisible"
      :form="{
        columns: permissionColumns,
        labelPosition: 'right',
        labelWidth: 100,
        rowProps: { gutter: 20 },
        colProps: { span: 12 }
      }"
      :dialog="{ title: '分配数据权限', width: 600, confirmLoading }"
      @confirm="handlePermissionSubmit"
    >
      <template #plus-field-deptIds>
        <dept-tree ref="deptRef" v-model="form.deptIds" />
      </template>
    </PlusDialogForm>
  </div>
</template>

<script lang="ts" setup>
import {
  computed,
  nextTick,
  onMounted,
  reactive,
  ref,
  resolveDirective,
  toRefs,
  useTemplateRef
} from "vue";
import type { FormRules } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  type FieldValues,
  type PlusColumn,
  type ButtonsCallBackParams,
  PlusDialogForm,
  PlusPage,
  PlusPageInstance,
  useTable
} from "plus-pro-components";
import { cloneDeep } from "lodash";
import {
  addSystemRole,
  changeRoleStatus,
  deleteSystemRole,
  getSystemRoleById,
  getSystemRoleDeptTree,
  getSystemRoleList,
  putSystemRoleDataScope,
  updateSystemRole
} from "@/api/system/role";
import MenuTree from "@/views/system/role/components/menuTree.vue";
import { getMenuListTreeSelect } from "@/api/system/menu";
import DeptTree from "@/views/system/role/components/deptTree.vue";
import { useRouter } from "vue-router";

defineOptions({
  name: "Role"
});

const router = useRouter();

onMounted(async () => {
  await getDeptList();
});

const menuRef = useTemplateRef("menuRef");
const deptRef = useTemplateRef("deptRef");

interface TableRow {
  id: number;
  name: string;
  status: string;
  tag: string;
  time: Date;
}

// 菜单列表

const plusPageInstance = ref<PlusPageInstance | null>(null);

const getList = async (query: Record<string, any>) => {
  let res = await getSystemRoleList(query);
  return {
    data: res.rows,
    total: res.total
  };
};

// 重新请求列表接口
const refresh = () => {
  plusPageInstance.value?.getList();
};

// 搜索之前函数
const handleBeforeSearch = (values: any) => {
  let params = cloneDeep(values);
  if (params.daterange && params.daterange.length === 2) {
    Reflect.set(params, "params", {});
    Reflect.set(params.params, "beginTime", values.daterange[0]);
    Reflect.set(params.params, "endTime", values.daterange[1]);
  } else {
    Reflect.deleteProperty(params, "params");
  }
  return params;
};

const dialogTitle = computed(() => (state.isCreate ? "新增" : "编辑"));
const { buttons } = useTable<TableRow[]>();

// 表格数据
const tableConfig: PlusColumn[] = [
  {
    label: "角色编号",
    prop: "roleId",
    hideInSearch: true
  },
  {
    label: "角色名称",
    prop: "roleName"
  },
  {
    label: "权限字符",
    prop: "roleKey"
  },
  {
    label: "显示顺序",
    prop: "roleSort",
    hideInSearch: true
  },
  {
    label: "组织ID",
    prop: "deptId",
    hideInTable: true,
    valueType: "tree-select",
    fieldProps: {
      checkStrictly: true,
      defaultExpandAll: false,
      style: { width: "100%" },
      data: computed(() => {
        return deptList.value;
      }),
      // el-tree-select 组件属性
      props: {
        label: "label",
        value: "id",
        children: "children"
      }
    }
  },
  {
    label: "状态",
    prop: "status",
    valueType: "select",
    fieldProps: {
      options: [
        { label: "正常", value: "0" },
        { label: "停用", value: "1" }
      ]
    },
    hideInTable: true
  },
  {
    label: "状态",
    prop: "status",
    valueType: "switch",
    hideInSearch: true,
    fieldProps: {
      placeholder: "角色状态",
      activeValue: "0",
      inactiveValue: "1"
    },
    editable: true,
    colProps: { span: 8 }
  },
  {
    label: "创建时间",
    prop: "createTime",
    hideInSearch: true
  },
  {
    label: "创建时间",
    prop: "daterange",
    valueType: "date-picker",
    fieldProps: {
      type: "daterange",
      startPlaceholder: "开始日期",
      endPlaceholder: "结束日期",
      style: { width: "100%" },
      unlinkPanels: true,
      valueFormat: "YYYY-MM-DD"
    },
    hideInTable: true
  }
];

/*--------------------表单--------------------*/

const dialogForm = ref(null);

interface State {
  dialogVisible: boolean;
  dialogPermissionVisible: boolean;
  confirmLoading: boolean;
  selectedIds: number[];
  isCreate: boolean;
  form: {
    businessType: string;
    deptId: number;
    menuIds: number[];
    deptIds: number[];
    remark: string;
    roleKey: string;
    roleName: string;
    roleSort: number;
    status: string;
    // isMenuCheckStrictly: string;
    dataScope: string;
  };
  rules: FormRules;
}

const state = reactive<State>({
  dialogVisible: false,
  dialogPermissionVisible: false,
  confirmLoading: false,
  selectedIds: [],
  isCreate: false,
  form: {
    businessType: "",
    deptId: null,
    menuIds: [],
    deptIds: [],
    remark: "",
    roleKey: "",
    roleName: "",
    roleSort: null,
    status: "",
    // isMenuCheckStrictly: "0",
    dataScope: ""
  },
  rules: {
    roleName: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
    roleSort: [{ required: true, message: "请输入角色排序", trigger: "blur" }]
  }
});

const deptList = ref([]);

const getDeptList = async () => {
  let res = await getSystemRoleDeptTree("2");
  if (res.code === 200) {
    deptList.value = res.depts;
  }
};

// 表单字段
const columns: PlusColumn[] = [
  {
    label: "角色名称",
    prop: "roleName",
    valueType: "input",
    colProps: { span: 24 },
    fieldProps: {
      clearable: true
    }
  },
  {
    label: "权限字符",
    prop: "roleKey",
    valueType: "input",
    colProps: { span: 24 },
    tooltip:
      "控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasRole('admin')`)",
    fieldProps: {
      clearable: true
    }
  },
  {
    label: "业务类型",
    prop: "businessType",
    valueType: "input",
    colProps: { span: 24 },
    fieldProps: {
      clearable: true
    }
  },
  {
    label: "组织ID",
    prop: "deptId",
    valueType: "tree-select",
    colProps: { span: 24 },
    fieldProps: {
      checkStrictly: true,
      defaultExpandAll: false,
      style: { width: "100%" },
      data: computed(() => {
        return deptList.value;
      }),
      // el-tree-select 组件属性
      props: {
        label: "label",
        value: "id",
        children: "children"
      }
    }
  },
  {
    label: "角色顺序",
    prop: "roleSort",
    valueType: "input-number",
    colProps: { span: 24 },
    fieldProps: {
      clearable: true,
      min: 0
    }
  },
  {
    label: "状态",
    prop: "status",
    valueType: "radio",
    colProps: { span: 24 },
    fieldProps: {
      clearable: true,
      options: [
        {
          label: "正常",
          value: "0"
        },
        {
          label: "停用",
          value: "1"
        }
      ]
    }
  },
  {
    label: "菜单权限",
    prop: "menuIds",
    colProps: { span: 24 },
    fieldProps: {}
  },
  {
    label: "备注",
    prop: "remark",
    valueType: "textarea",
    colProps: { span: 24 },
    fieldProps: {
      clearable: true,
      minRow: 2
    }
  }
];

const permissionColumns: PlusColumn[] = [
  {
    label: "角色名称",
    prop: "roleName",
    colProps: { span: 24 },
    fieldProps: {
      disabled: true
    }
  },
  {
    label: "权限字符",
    prop: "roleKey",
    colProps: { span: 24 },
    fieldProps: {
      disabled: true
    }
  },
  {
    label: "权限范围",
    prop: "dataScope",
    valueType: "select",
    colProps: { span: 24 },
    fieldProps: {
      options: [
        {
          label: "全部数据权限",
          value: "1"
        },
        {
          label: "自定义数据权限",
          value: "2"
        },
        {
          label: "本部门数据权限",
          value: "3"
        },
        {
          label: "本部门及以下数据权限",
          value: "4"
        },
        {
          label: "仅本人数据权限",
          value: "5"
        }
      ]
    }
  },
  {
    label: "数据权限",
    prop: "deptIds",
    colProps: { span: 24 },
    hideInForm: computed(() => form.value.dataScope !== "2")
  }
];

// 创建
const handleCreate = (): void => {
  form.value = {
    businessType: "",
    deptId: null,
    menuIds: [],
    deptIds: [],
    remark: "",
    roleKey: "",
    roleName: "",
    roleSort: null,
    status: "0",
    // isMenuCheckStrictly: "0",
    dataScope: null
  };
  state.isCreate = true;
  state.dialogVisible = true;
};

// 选择
const handleSelect = (data: any) => {
  state.selectedIds = [...data].map(item => item.id);
};

const handleFormChange = (values: FieldValues) => {
  console.log(values);
};

const handleTableChange = (values: FieldValues) => {
  console.log(values);
  ElMessageBox.confirm("确定修改此数据吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(async () => {
      try {
        let res = await changeRoleStatus(values.row.roleId, values.row.status);
        if (res.code === 200) {
          ElMessage.success("修改成功");
          refresh();
        } else {
          ElMessage.error(res.msg);
        }
      } catch (e) {
        ElMessage.error("修改失败");
      }
    })
    .finally(() => {
      refresh();
    });
};

const handleOpen = () => {
  console.log("open");
  if (!state.isCreate) {
    console.log(menuRef.value);
  }
};

const handleSubmit = async (values: FieldValues) => {
  console.log(values, "Submit");
  confirmLoading.value = true;
  console.log(menuRef.value.getAllKeys());
  let params = form.value;
  params.menuIds = menuRef.value.getAllKeys();
  if (state.isCreate) {
    try {
      // params.isMenuCheckStrictly = "0";
      let res = await addSystemRole(params);
      if (res.code === 200) {
        ElMessage.success("新增成功");
        confirmLoading.value = false;
        dialogVisible.value = false;
        refresh();
      } else {
        ElMessage.error(res.msg);
      }
    } finally {
      confirmLoading.value = false;
    }
  } else {
    // 编辑
    try {
      // params.isMenuCheckStrictly = "0";
      let res = await updateSystemRole(params);
      if (res.code === 200) {
        ElMessage.success("修改成功");
        confirmLoading.value = false;
        dialogVisible.value = false;
        refresh();
      } else {
        ElMessage.error(res.msg);
      }
    } finally {
      confirmLoading.value = false;
    }
  }
};

const handlePermissionSubmit = async (values: FieldValues) => {
  confirmLoading.value = true;
  try {
    let params = form.value;
    params.menuIds = deptRef.value.getAllKeys();
    let res = await putSystemRoleDataScope(params);
    if (res.code === 200) {
      ElMessage.success("修改成功");
      confirmLoading.value = false;
      dialogPermissionVisible.value = false;
      refresh();
    } else {
      ElMessage.error(res.msg);
    }
  } finally {
    confirmLoading.value = false;
  }
};

const handleSubmitError = (err: any) => {
  console.log(err, "err");
};
const handleClose = () => {
  // 重置表单
  /*nextTick(() => {
    if (dialogForm.value) {
      dialogForm.value.formInstance.resetFields();
    }
  });*/
  console.log(dialogForm.value.formInstance);
  dialogForm.value.formInstance.resetFields();
};

// 权限
const perms = resolveDirective("perms");

buttons.value = [
  {
    // 修改
    text: "修改",
    code: "edit",
    // props v0.1.16 版本新增函数类型
    props: { type: "primary" },
    show: (row: any) => row.roleKey !== "admin",
    directives: [[perms, "system:role:edit"]]
  },
  {
    // 删除
    text: "删除",
    code: "delete",
    props: { type: "danger" },
    show: (row: any) => row.roleKey !== "admin",
    directives: [[perms, "system:role:remove"]]
  },
  {
    text: "数据权限",
    code: "dataPermission",
    props: { type: "primary" },
    show: (row: any) => row.roleKey !== "admin",
    directives: [[perms, "system:role:dataPermission"]]
  }
];

const handleTableOption = ({ row, buttonRow }: ButtonsCallBackParams): void => {
  console.log(row);
  switch (buttonRow.code) {
    case "edit":
      handleEdit(row.roleId);
      break;
    case "delete":
      handleDelete(row.roleId);
      break;
    case "dataPermission":
      handleDataPermission(row.roleId);
      break;
  }
};

const handleEdit = async (id: string) => {
  let res = await getSystemRoleById(id);
  let res1 = await getMenuListTreeSelect(id);
  console.log(res, res1);
  form.value = res.data;
  form.value.menuIds = res1.checkedKeys;
  state.isCreate = false;
  state.dialogVisible = true;
};

const handleDelete = (id: string) => {
  ElMessageBox.confirm("确定删除吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
    let res = await deleteSystemRole(id);
    if (res.code === 200) {
      ElMessage.success(res.msg);
      refresh();
    } else {
      ElMessage.error(res.msg);
    }
  });
};

const handleDataPermission = async (id: string) => {
  console.log(id);
  let res = await getSystemRoleById(id);
  let res1 = await getSystemRoleDeptTree(id);
  form.value = res.data;
  form.value.deptIds = res1.checkedKeys;
  state.isCreate = false;
  state.dialogPermissionVisible = true;
};

const { form, confirmLoading, rules, dialogVisible, dialogPermissionVisible } =
  toRefs(state);
</script>
