<template>
  <div class="subjects-manage">
    <Block class="header-block tw-flex tw-items-center">
      <a-form layout="inline" class="tw-flex-1">
        <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-select
            v-model:value="query.examId"
            :filterOption="false"
            show-search
            @search="(name:string) => queryExamList(name, 'list')"
            placeholder="考试批次"
          >
            <a-select-option value="">全部</a-select-option>
            <a-select-option
              v-for="exam in examTableData.result"
              :key="exam.id"
              :value="`${exam.id}`"
              >{{ exam.name }}</a-select-option
            >
          </a-select>
        </a-form-item>
        <a-form-item label="分组状态">
          <a-select v-model:value="query.groupFinish" placeholder="考试批次">
            <a-select-option :value="0">全部</a-select-option>
            <a-select-option :value="1">已完成</a-select-option>
            <a-select-option :value="2">未完成</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="科目代码">
          <a-input
            v-model:value="query.courseCode"
            placeholder="科目代码"
            maxlength="50"
          ></a-input>
        </a-form-item>
        <a-form-item label="科目名称">
          <a-input
            v-model:value="query.courseName"
            placeholder="科目名称"
            maxlength="50"
          ></a-input>
        </a-form-item>
        <a-form-item label="试卷总分" class="range-item">
          <a-input v-model:value="query.totalScoreMin"></a-input>
          至
          <a-input v-model:value="query.totalScoreMax"></a-input>
        </a-form-item>
        <a-form-item>
          <a-button
            class="search-button"
            type="primary"
            @click="querySubjectsList"
            >查询</a-button
          >
        </a-form-item>
      </a-form>
      <a-dropdown-button type="primary">
        <template #overlay>
          <a-menu>
            <a-menu-item key="1" @click="showImportModalType('subject')"
              >导入科目</a-menu-item
            >
            <a-menu-item key="2" @click="showImportModalType('struct')"
              >导入主观题</a-menu-item
            >
          </a-menu>
        </template>
        <template #icon><DownOutlined /></template>
        导入
      </a-dropdown-button>
      <a-button
        type="primary"
        class="tw-flex tw-items-center operation-button"
        @click="downloadPaperStruct"
      >
        <template #icon>
          <UploadOutlined />
        </template>
        导出
      </a-button>
    </Block>
    <Block class="subjects-table">
      <a-table
        :columns="columns"
        :data-source="subjectsTableData.result"
        :pagination="{
          total: subjectsTableData.totalCount,
          pageSize: query.pageSize,
        }"
        @change="currentPageChange"
        :row-class-name="
          (_:any, index:number) => (index % 2 === 1 ? 'table-striped' : null)
        "
      >
        <template #bodyCell="{ column, record, index, text }">
          <template v-if="column.dataIndex === 'index'">
            {{ index + 1 }}
          </template>
          <template v-else-if="column.dataIndex === 'courseName'">
            {{ text }}
            <a-tooltip placement="right">
              <template #title>
                <span>主观分未完成分组</span>
              </template>
              <img
                v-if="!record.groupFinish"
                class="star-icon"
                src="@imgs/common/star-icon.png"
              />
            </a-tooltip>
          </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>
      </a-table>
    </Block>
    <a-modal
      v-model:visible="showImportModal"
      :maskClosable="false"
      :title="`导入${uploadQuery.type === 'subject' ? '科目' : '主观题'}`"
      okText="确认上传"
      cancelText="取消"
      @ok="onImport"
      :afterClose="resetFields"
    >
      <a-form :labelCol="{ span: 6 }">
        <a-form-item label="学校名称" v-bind="validateInfos.schoolId">
          <a-select
            v-model:value="uploadQuery.schoolId"
            show-search
            :filterOption="false"
            @search="(name: string) => querySchoolList(name,'form')"
            placeholder="学校名称"
          >
            <a-select-option
              v-for="school in uploadQuery.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.examId">
          <a-select
            v-model:value="uploadQuery.examId"
            :filterOption="false"
            show-search
            @search="(name:string) => queryExamList(name, 'form')"
            placeholder="考试批次"
          >
            <a-select-option
              v-for="exam in uploadQuery.examTableData.result"
              :key="exam.id"
              :value="`${exam.id}`"
              >{{ exam.name }}</a-select-option
            >
          </a-select>
        </a-form-item>
        <a-form-item
          :label="`${
            uploadQuery.type === 'subject' ? '科目' : '主观题'
          }导入文件`"
          v-bind="validateInfos.fileList"
        >
          <a-upload
            :file-list="uploadQuery.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="PageSubjects">
import { onBeforeMount, reactive, ref, watch } from "vue";
import {
  UploadOutlined,
  CheckCircleFilled,
  CloseCircleFilled,
  DownOutlined,
} from "@ant-design/icons-vue";

import Block from "@/components/block/index.vue";
import { message, TableColumnType, UploadProps } from "ant-design-vue";
import { Form } from "ant-design-vue";
import {
  getSubjectsListHttp,
  importSubjectsHttp,
  importPaperStructHttp,
  downloadPaperStructHttp,
  downloadSubjectTemplateHttp,
  downloadPaperStructTemplateHttp,
} from "@/apis/struct";
import { getSchoolListHttp } from "@/apis/school";
import { getExamListHttp } from "@/apis/exam";
import { useMainStore } from "@/store/main";
import { throttle } from "lodash-es";
import { fileTypeCheck } from "@/utils/file-type";

type ImportType = "subject" | "struct";

const mainStore = useMainStore();

const showImportModal = ref(false);

const tableLoading = ref(false);

const ImportDownloadApi: Record<
  ImportType,
  {
    upload: typeof importSubjectsHttp;
    download: typeof downloadSubjectTemplateHttp;
  }
> = {
  subject: {
    upload: importSubjectsHttp,
    download: downloadSubjectTemplateHttp,
  },
  struct: {
    upload: importPaperStructHttp,
    download: downloadPaperStructTemplateHttp,
  },
};

/** 导入参数 */
const uploadQuery = reactive<{
  type: ImportType;
  schoolId?: string | number;
  examId?: string;
  fileList: UploadProps["fileList"];
  schoolTableData: MultiplePageData<SchoolListInfo>;
  examTableData: MultiplePageData<ExamListInfo>;
}>({
  type: "subject",
  schoolTableData: { totalCount: 0, result: [] },
  examTableData: { totalCount: 0, result: [] },
  schoolId: void 0,
  examId: void 0,
  fileList: [],
});

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

const { validate, validateInfos, resetFields } = Form.useForm(
  uploadQuery,
  uploadRules
);

/** 查询参数 */
const query = reactive<
  Omit<FetchSubjectsListQuery, "groupFinish"> & { groupFinish: number }
>({
  /** 科目代码 */
  courseCode: "",
  courseName: "",
  /** 考试id */
  examId: "",
  /** 	分组状态 */
  groupFinish: 0,
  /** 学校id */
  schoolId: mainStore.systemUserInfo?.schoolId || "",
  /** 总分截止值 */
  totalScoreMax: "",
  /** 总分起始值 */
  totalScoreMin: "",
  pageSize: 10,
  pageNumber: 1,
});

/** table配置 */
const columns: TableColumnType[] = [
  { title: "序号", dataIndex: "index", align: "center", width: 60 },
  {
    title: "科目代码",
    dataIndex: "courseCode",
    align: "center",
    width: 120,
    ellipsis: true,
  },
  { title: "科目名称", dataIndex: "courseName", ellipsis: true },
  {
    title: "主观总分",
    dataIndex: "subjectiveScore",
    align: "center",
    width: 100,
  },
  { title: "试卷总分", dataIndex: "totalScore", align: "center", width: 100 },
  { title: "分组数", dataIndex: "groupCount", align: "center", width: 80 },
];

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

/** 考试列表信息 */
const examTableData = reactive<MultiplePageData<ExamListInfo>>({
  totalCount: 0,
  result: [],
});

/** 科目列表信息 */
const subjectsTableData = reactive<MultiplePageData<SubjectsListInfo>>({
  totalCount: 0,
  result: [],
});

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

/** 查询考试列表 */
const queryExamList = throttle(
  async (name: string = "", type: "list" | "form" = "list") => {
    try {
      const isList = type === "list";
      const schoolId = isList ? query.schoolId : uploadQuery.schoolId;
      if (!schoolId) {
        return Promise.reject(`schoolId got : ${schoolId}`);
      }
      const { result = [], totalCount } = await getExamListHttp({
        pageNumber: 1,
        pageSize: 10,
        name,
        schoolId,
      });
      Object.assign(isList ? examTableData : uploadQuery.examTableData, {
        result,
        totalCount,
      });
    } catch (error) {
      return Promise.reject(error);
    }
  },
  100
);

/** 查询科目列表 */
const querySubjectsList = async () => {
  try {
    tableLoading.value = true;
    const { result = [], totalCount } = await getSubjectsListHttp({
      ...query,
      groupFinish: [void 0, true, false][query.groupFinish],
    });
    Object.assign(subjectsTableData, { result, totalCount });
  } catch (error) {
    return Promise.reject(error);
  }
  tableLoading.value = false;
};

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

watch(
  () => query.schoolId,
  () => {
    query.examId = "";
    Object.assign(examTableData, { result: [], totalCount: 0 });
    if (query.schoolId) {
      queryExamList("", "list");
    }
  }
);

watch(
  () => uploadQuery.schoolId,
  () => {
    uploadQuery.examId = void 0;
    Object.assign(uploadQuery.examTableData, { result: [], totalCount: 0 });
    if (uploadQuery.schoolId) {
      queryExamList("", "form");
    }
  }
);

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

/** 导出主观题 */
const downloadPaperStruct = async () => {
  try {
    await downloadPaperStructHttp({
      ...query,
      groupFinish: [void 0, true, false][query.groupFinish],
    });
  } catch (error) {
    return Promise.reject(error);
  }
};

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

const beforeUpload: UploadProps["beforeUpload"] = async (file) => {
  await fileTypeCheck(file, ["xls", "xlsx"]).catch((error) => {
    message.error("文件类型错误, 请使用导入模板编辑");
    return Promise.reject(error);
  });
  uploadQuery.fileList = [file];
  return false;
};

/** 下载导入模板 */
const downloadTemplate = async () => {
  try {
    await ImportDownloadApi[uploadQuery.type].download();
  } catch (error) {
    return Promise.reject(error);
  }
};

/** 显示导入弹窗 */
const showImportModalType = async (type: ImportType) => {
  uploadQuery.type = type;
  uploadQuery.schoolId = query.schoolId || mainStore.systemUserInfo?.schoolId;
  showImportModal.value = true;
  querySchoolList("", "form");
};

/** 导入数据 */
const onImport = async () => {
  try {
    const valid = await validate();
    if (valid) {
      const formData = new FormData();
      formData.append("examId", uploadQuery.examId || "");
      uploadQuery.fileList?.forEach((file: any) => {
        formData.append("file", file);
      });
      await ImportDownloadApi[uploadQuery.type].upload(formData);
      querySubjectsList();
      showImportModal.value = false;
    }
  } catch (error) {
    return Promise.reject(error);
  }
};

onBeforeMount(async () => {
  try {
    await querySchoolList();
    if (
      schoolTableData.result
        .map((school) => `${school.id}`)
        .some((id) => id === `${query.schoolId}`)
    ) {
      await queryExamList("", "list");
      await querySubjectsList();
    }
  } catch (error) {
    console.error(error);
  }
});
</script>

<style scoped lang="less">
.subjects-manage {
  .header-block {
    .ant-input {
      width: 160px;
    }
    :deep(.ant-select-selector) {
      width: 160px;
    }
    :deep(.ant-form-item) {
      margin-bottom: 8px;
    }
    .range-item {
      .ant-input {
        width: 69px;
      }
    }
    .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: 8px;
    }
  }
  .subjects-table {
    .star-icon {
      width: 14px;
      height: 14px;
      display: inline-block;
      vertical-align: middle;
    }
  }
}
</style>
