<template>
  <div class="user-manage">
    <Block class="header-block tw-flex tw-items-center">
      <a-form layout="inline">
        <a-form-item label="学校名称">
          <a-select
            v-model:value="query.schoolId"
            show-search
            :filterOption="false"
            @search="(name:string) => querySchoolList(name,'list')"
            placeholder="学校名称"
          >
            <a-select-option
              v-for="school in schoolTableData.result"
              :key="school.id"
              :value="school.id"
              >{{ school.name }}</a-select-option
            >
          </a-select>
        </a-form-item>
        <a-form-item label="登录名">
          <a-input
            v-model:value="query.loginName"
            placeholder="登录手机号"
          ></a-input>
        </a-form-item>
        <a-form-item label="角色">
          <a-select v-model:value="query.role" placeholder="用户角色">
            <a-select-option :value="void 0">全部</a-select-option>
            <a-select-option value="SCHOOL_ADMIN">{{
              ROLE.SCHOOL_ADMIN
            }}</a-select-option>
            <a-select-option value="SECTION_LEADER">{{
              ROLE.SECTION_LEADER
            }}</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item>
          <a-button class="search-button" type="primary" @click="queryUserList"
            >查询</a-button
          >
        </a-form-item>
      </a-form>
      <a-button
        type="primary"
        class="tw-flex tw-items-center operation-button"
        @click="toggleAddUserModal"
      >
        <template #icon>
          <PlusCircleOutlined />
        </template>
        新增
      </a-button>
      <a-button
        type="primary"
        class="tw-flex tw-items-center operation-button"
        @click="importUserList"
      >
        <template #icon>
          <DownloadOutlined />
        </template>
        导入
      </a-button>
    </Block>
    <Block class="user-table">
      <a-table
        :columns="columns"
        :data-source="userTableData.result"
        :pagination="{
          total: userTableData.totalCount,
          pageSize: query.pageSize,
        }"
        @change="currentPageChange"
        :row-class-name="
          (_:any, index:number) => (index % 2 === 1 ? 'table-striped' : null)
        "
      >
        <template #bodyCell="{ column, record, index }">
          <template v-if="column.dataIndex === 'index'">
            {{ index + 1 }}
          </template>
          <template v-else-if="column.dataIndex === 'enable'">
            <template v-if="record.enable">
              <CheckCircleFilled style="color: #30bf78" />
            </template>
            <template v-else>
              <CloseCircleFilled style="color: #f4664a" />
            </template>
          </template>
          <template v-else-if="column.dataIndex === 'operation'">
            <div
              class="tw-flex tw-items-center"
              v-if="record.role !== 'SUPER_ADMIN'"
            >
              <span
                class="tw-cursor-pointer tw-p-2"
                @click="updateUserStatus(record)"
                >{{ record.enable ? "禁用" : "启用" }}</span
              >
              <span
                class="tw-cursor-pointer tw-p-2 tw-ml-1"
                @click="onEdit(record)"
                >编辑</span
              >
              <span
                class="tw-cursor-pointer tw-p-2 tw-ml-1"
                @click="onResetPwd(record)"
                >重置密码
              </span>
            </div>
          </template>
        </template>
      </a-table>
    </Block>
    <a-modal
      v-model:visible="showModal"
      :title="`${!userInfo.id ? '新增' : '编辑'}用户`"
      okText="确定"
      cancelText="取消"
      :maskClosable="false"
      @ok="onPutUser"
      :afterClose="resetUserFields"
    >
      <a-form :labelCol="{ span: 6 }">
        <a-form-item label="学校" v-bind="validateInfos.schoolId">
          <a-select
            v-model:value="userInfo.schoolId"
            show-search
            :disabled="!!userInfo.id"
            :filterOption="false"
            @search="(name:string) => querySchoolList(name,'form')"
            placeholder="学校名称"
          >
            <a-select-option
              v-for="school in userInfo.schoolTableData.result"
              :key="school.id"
              :value="school.id"
              >{{ school.name }}</a-select-option
            >
          </a-select>
        </a-form-item>
        <a-form-item label="姓名" v-bind="validateInfos.name">
          <a-input
            v-model:value="userInfo.name"
            placeholder="请输入姓名"
          ></a-input>
        </a-form-item>
        <a-form-item label="登录名" v-bind="validateInfos.loginName">
          <a-input
            :disabled="!!userInfo.id"
            v-model:value="userInfo.loginName"
            maxlength="11"
            :placeholder="
              userInfo.role === 'SECTION_LEADER'
                ? '请输入登录手机号'
                : '请输入登录名'
            "
          ></a-input>
        </a-form-item>
        <a-form-item
          v-if="!userInfo.id"
          label="密码"
          v-bind="validateInfos.passwd"
        >
          <a-input-password
            v-model:value="userInfo.passwd"
            placeholder="请输入密码"
          ></a-input-password>
        </a-form-item>
        <a-form-item label="角色" v-bind="validateInfos.role">
          <a-select v-model:value="userInfo.role" placeholder="请选择角色">
            <a-select-option value="SCHOOL_ADMIN">{{
              ROLE.SCHOOL_ADMIN
            }}</a-select-option>
            <a-select-option value="SECTION_LEADER">{{
              ROLE.SECTION_LEADER
            }}</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item
          v-if="userInfo.role === 'SECTION_LEADER'"
          label="所属科目"
          v-bind="validateInfos.course"
        >
          <a-textarea
            v-model:value="userInfo.course"
            placeholder="请填写所属科目代码, 以','分隔;"
          ></a-textarea>
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:visible="showResetPwdModal"
      title="密码设置"
      okText="确定"
      cancelText="取消"
      :maskClosable="false"
      @ok="onUpdateUserPwd"
      :afterClose="resetPwdFields"
    >
      <a-form :labelCol="{ span: 3 }">
        <a-form-item label="密码" v-bind="validatePwdInfos.passwd">
          <a-input-password v-model:value="resetPwd.passwd"></a-input-password>
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:visible="showImportModal"
      :maskClosable="false"
      title="导入用户"
      okText="确认上传"
      cancelText="取消"
      @ok="onImportUserList"
      :afterClose="resetImportFields"
    >
      <a-form :labelCol="{ span: 6 }">
        <a-form-item label="学校名称" v-bind="validateImportInfos.schoolId">
          <a-select
            v-model:value="importUserForm.schoolId"
            show-search
            :filterOption="false"
            @search="(name: string) => querySchoolList(name,'import')"
            placeholder="学校名称"
          >
            <a-select-option
              v-for="school in importUserForm.schoolTableData.result"
              :key="school.id"
              :value="school.id"
              >{{ school.name }}</a-select-option
            >
          </a-select>
        </a-form-item>
        <a-form-item label="用户导入文件" v-bind="validateImportInfos.fileList">
          <a-upload
            :file-list="importUserForm.fileList"
            :before-upload="beforeUpload"
            @remove="handleRemove"
            :max-count="1"
            type="primary"
          >
            <a-button>
              <upload-outlined></upload-outlined>
              选择文件
            </a-button>
            <a class="tw-ml-4 tw-align-bottom" @click.stop="downloadTemplate">
              下载导入模板
            </a>
          </a-upload>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts" name="PageUsers">
import { nextTick, reactive, ref, watch, markRaw } from "vue";
import {
  PlusCircleOutlined,
  CheckCircleFilled,
  CloseCircleFilled,
  DownloadOutlined,
} from "@ant-design/icons-vue";
import {
  getUserListHttp,
  updateUserStatusHttp,
  editUserInfoHttp,
  resetUserPwdHttp,
  importUserHttp,
  downloadImportUserHttp,
} from "@/apis/user";
import Block from "@/components/block/index.vue";
import { message } from "ant-design-vue";
import { Form } from "ant-design-vue";
import { getSchoolListHttp } from "@/apis/school";
import type { UploadProps, TableColumnType } from "ant-design-vue";
import { useMainStore } from "@/store/main";
import { throttle } from "lodash-es";
import { ROLE } from "@/constants/dicts";

const mainStore = useMainStore();

const showModal = ref(false);
const showResetPwdModal = ref(false);
const showImportModal = ref(false);

const importUserForm = reactive<{
  schoolId: string;
  fileList: UploadProps["fileList"];
  schoolTableData: MultiplePageData<SchoolListInfo>;
}>({
  schoolId: "",
  fileList: [],
  schoolTableData: { totalCount: 0, result: [] },
});

const importRules = {
  schoolId: [{ required: true, message: "请选择学校" }],
  fileList: [
    { required: true, type: "array", len: 1, message: "请选择导入文件" },
  ],
};

const userInfo = reactive<
  EditUserInfo & { schoolTableData: MultiplePageData<SchoolListInfo> }
>({
  schoolId: "",
  name: "",
  loginName: "",
  course: "",
  passwd: void 0,
  role: void 0,
  id: void 0,
  schoolTableData: { totalCount: 0, result: [] },
});

const resetPwd = reactive({
  passwd: "",
  userId: "",
});

const editUserRules = () => ({
  name: [{ required: true, message: "请填写用户姓名" }],
  role: [{ required: true, message: "请选择用户角色" }],
});

const addUserRules = () => ({
  schoolId: [{ required: true, message: "请选择用户所属学校" }],
  loginName: [{ required: true, message: "请填写登录名" }],
  passwd: [
    { required: true, message: "请填写登录密码" },
    {
      pattern: /^[a-zA-Z0-9]{6,18}$/,
      message: "密码只能由数字、字母组成，长度6-18个字符",
    },
  ],
});

const userRules = reactive({
  ...addUserRules(),
  ...editUserRules(),
});

const pwdRules = {
  passwd: [
    { required: true, message: "请填写登录密码" },
    {
      pattern: /^[a-zA-Z0-9]{6,18}$/,
      message: "密码只能由数字、字母组成，长度6-18个字符",
    },
  ],
};

const {
  validate,
  validateInfos,
  resetFields: resetUserFields,
} = Form.useForm(userInfo, userRules);

const {
  validate: validatePwd,
  validateInfos: validatePwdInfos,
  resetFields: resetPwdFields,
} = Form.useForm(resetPwd, pwdRules);

const {
  validate: validateImport,
  validateInfos: validateImportInfos,
  resetFields: resetImportFields,
} = Form.useForm(importUserForm, importRules);

/** 请求参数 */
const query = reactive<FetchUserListQuery>({
  loginName: "",
  schoolId: mainStore.systemUserInfo?.schoolId || "",
  role: void 0,
  pageNumber: 1,
  pageSize: 10,
});

/** table配置 */
const columns: TableColumnType[] = [
  { title: "序号", dataIndex: "index", align: "center" },
  { title: "ID", dataIndex: "id" },
  { title: "姓名", dataIndex: "name" },
  { title: "登录名", dataIndex: "loginName" },
  { title: "学校", dataIndex: "schoolName", align: "center" },
  { title: "角色", dataIndex: "roleName" },
  { title: "更新时间", dataIndex: "updateTime" },
  { title: "状态", dataIndex: "enable" },
  { title: "操作", dataIndex: "operation" },
];

/** 用户列表信息 */
const userTableData = reactive<MultiplePageData<UserInfo>>({
  totalCount: 0,
  result: [],
});

/** 学校列表信息 */
const schoolTableData = reactive<MultiplePageData<SchoolListInfo>>({
  totalCount: 0,
  result: [],
});

/** 查询学校列表 */
const querySchoolList = throttle(
  async (name: string = "", type: "list" | "form" | "import" = "list") => {
    const isList = type === "list";
    const isForm = type === "form";
    try {
      const { result = [], totalCount } = await getSchoolListHttp({
        name,
        pageNumber: 1,
        pageSize: 10,
      });
      Object.assign(
        isList
          ? schoolTableData
          : isForm
          ? userInfo.schoolTableData
          : importUserForm.schoolTableData,
        {
          result,
          totalCount,
        }
      );
    } catch (error) {
      return Promise.reject(error);
    }
  },
  100
);

/** 显示新增用户弹窗 */
const toggleAddUserModal = (show: boolean = true) => {
  if (show) {
    if (userInfo.id) {
      Object.assign(userRules, { schoolId: [], loginName: [], passwd: [] });
    } else {
      Object.assign(userInfo, { schoolId: query.schoolId || mainStore.systemUserInfo?.schoolId });
      Object.assign(userRules, { ...addUserRules() });
    }
    querySchoolList("", "form");
  }
  nextTick(() => {
    showModal.value = show;
  });
};

/** 查询用户列表 */
const queryUserList = async () => {
  try {
    const { result = [], totalCount } = await getUserListHttp(query);
    Object.assign(userTableData, { result, totalCount });
  } catch (error) {
    console.error(error);
  }
};

watch(() => query.pageNumber, queryUserList);

/* 启用/禁用 */
const updateUserStatus = (record: UserInfo) => {
  updateUserStatusHttp({ enable: !record.enable, ids: [record.id] }).then(
    queryUserList
  );
};

/** 编辑用户 */
const onEdit = (record: UserInfo) => {
  Object.assign(userInfo, {
    course: record.courseCodes?.join(","),
    id: record.id,
    schoolId: record.schoolId,
    name: record.name,
    loginName: record.loginName,
    role: record.role,
  });
  toggleAddUserModal(true);
};

/** 重置密码 */
const onResetPwd = (record: UserInfo) => {
  Object.assign(resetPwd, { passwd: "", userId: `${record.id}` });
  showResetPwdModal.value = true;
};

/** 新增用户 */
const onPutUser = () => {
  const role = userInfo.role;
  const isEdit = !!userInfo.id;
  if (!isEdit) {
    if (role === "SECTION_LEADER") {
      Object.assign(userRules, {
        loginName: [
          { required: true, message: "请填写登录手机号" },
          // @ts-ignore
          { pattern: /\d{11}/, message: "请填写正确的手机号" },
        ],
      });
    } else {
      Object.assign(userRules, {
        loginName: [{ required: true, message: "请填写登录名" }],
      });
    }
  }
  validate().then((valid) => {
    if (valid) {
      const { role, course, schoolTableData, ...info } = userInfo;
      editUserInfoHttp({
        ...info,
        role,
        course: role === "SECTION_LEADER" ? course : "",
      }).then(() => {
        message.success(`${isEdit ? "修改" : "添加"}成功`);
        queryUserList();
        toggleAddUserModal(false);
      });
    }
  });
};

/** 导入用户 */
const importUserList = () => {
  showImportModal.value = true;
  Object.assign(importUserForm, {
    schoolId: query.schoolId || mainStore.systemUserInfo?.schoolId,
  });
  querySchoolList("", "import");
};

const handleRemove: UploadProps["onRemove"] = (file) => {
  const index = importUserForm.fileList!.indexOf(file);
  const newFileList = importUserForm.fileList!.slice();
  newFileList.splice(index, 1);
  importUserForm.fileList = newFileList;
};

const beforeUpload: UploadProps["beforeUpload"] = (file) => {
  importUserForm.fileList = [file];
  return false;
};

/** 下载导入模板 */
const downloadTemplate = async () => {
  try {
    await downloadImportUserHttp();
  } catch (error) {
    return Promise.reject(error);
  }
};

const onImportUserList = async () => {
  try {
    const valid = await validateImport();
    if (valid) {
      const formData = new FormData();
      formData.append("schoolId", `${importUserForm.schoolId}`);
      importUserForm.fileList?.forEach((file: any) => {
        formData.append("file", file);
      });
      await importUserHttp(formData);
      queryUserList();
      showImportModal.value = false;
    }
  } catch (error) {
    return Promise.reject(error);
  }
};

/** 修改密码 */
const onUpdateUserPwd = () => {
  validatePwd().then((valid) => {
    if (valid) {
      resetUserPwdHttp(resetPwd).then(() => {
        message.success(`重置成功`);
        showResetPwdModal.value = false;
      });
    }
  });
};

const currentPageChange = ({ current }: { current: number }) => {
  query.pageNumber = current;
};

querySchoolList();

/** effect */
if (query.schoolId) {
  queryUserList();
}
</script>

<style scoped lang="less">
.user-manage {
  .header-block {
    .ant-input {
      width: 160px;
    }
    :deep(.ant-select-selector) {
      width: 160px;
    }
    .search-button {
      background-color: @font-color;
      color: @white;
      border: none;
      width: 56px;
      padding: 0;
      &:after {
        display: none;
        opacity: 0;
      }
    }

    .operation-button {
      width: 72px;
      padding: 0;
      margin-left: auto;
      & ~ .operation-button {
        margin-left: 8px;
      }
    }
  }
  .user-table {
  }
}
</style>
