<template>
  <div class="part-box is-filter">
    <el-form inline>
      <el-form-item label="姓名">
        <el-input
          v-model.trim="searchModel.name"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="准考证号">
        <el-input
          v-model.trim="searchModel.examNumber"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="密号">
        <el-input
          v-model.trim="searchModel.secretNumber"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="学号">
        <el-input
          v-model.trim="searchModel.studentCode"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="科目">
        <select-subject v-model="searchModel.subjectCode"></select-subject>
      </el-form-item>
      <el-form-item label="层次">
        <select-option v-model="searchModel.subjectLevel" type="subjectLevel">
        </select-option>
      </el-form-item>
      <el-form-item label="专业类型">
        <select-option
          v-model="searchModel.subjectCategory"
          type="subjectCategory"
        >
        </select-option>
      </el-form-item>
      <el-form-item label="状态">
        <el-space>
          <el-select
            v-model="searchModel.upload"
            placeholder="不限"
            clearable
            style="width: 120px"
          >
            <el-option label="已上传" :value="true" />
            <el-option label="未上传" :value="false" />
          </el-select>
          <el-select
            v-model="searchModel.absent"
            placeholder="不限"
            clearable
            style="width: 120px"
          >
            <el-option label="缺考" :value="true" />
            <el-option label="正常" :value="false" />
          </el-select>
          <el-select
            v-model="searchModel.breach"
            placeholder="不限"
            clearable
            style="width: 120px"
          >
            <el-option label="违纪" :value="true" />
            <el-option label="正常" :value="false" />
          </el-select>
          <el-select
            v-model="searchModel.manualAbsent"
            placeholder="不限"
            clearable
            style="width: 140px"
          >
            <el-option label="人工指定缺考" :value="true" />
            <el-option label="正常" :value="false" />
          </el-select>
        </el-space>
      </el-form-item>
      <el-form-item label="签到表编号">
        <el-input
          v-model.trim="searchModel.packageCode"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="批次编号">
        <el-input
          v-model.trim="searchModel.batchCode"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="学院">
        <select-option
          v-model="searchModel.college"
          type="college"
        ></select-option>
      </el-form-item>
      <el-form-item label="班级">
        <select-option
          v-model="searchModel.className"
          type="className"
        ></select-option>
      </el-form-item>
      <el-form-item label="任课老师">
        <el-input
          v-model.trim="searchModel.teacher"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="考点">
        <el-input
          v-model.trim="searchModel.examSite"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="考场">
        <el-input
          v-model.trim="searchModel.examRoom"
          placeholder="请输入"
          clearable
        >
        </el-input>
      </el-form-item>
      <el-form-item label="扫描张数">
        <el-input-number
          v-model.number="searchModel.sheetCount"
          :min="0"
          :max="30"
          :step="1"
          :precision="0"
          :controls="false"
          step-strictly
          style="width: 100px"
          placeholder="请输入"
        >
        </el-input-number>
      </el-form-item>
    </el-form>
    <el-divider class="form-divider" />
    <div class="part-action box-justify">
      <el-space wrap>
        <el-button type="primary" @click="toPage(1)">查询</el-button>
        <el-button type="success" @click="onAdd">添加</el-button>
        <el-button @click="onImport">导入</el-button>
        <el-dropdown @command="onImportCommand">
          <el-button class="is-shade">
            导入名单
            <el-icon class="el-icon--right"><CaretBottom /> </el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="breach">违纪名单</el-dropdown-item>
              <el-dropdown-item command="absent">缺考名单</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-button @click="onExport">导出</el-button>
      </el-space>

      <table-field
        v-model="headFields"
        :fields="tableFields"
        @change="handleFieldChange"
      ></table-field>
    </div>
  </div>
  <div class="part-box">
    <el-table
      class="page-table"
      :data="dataList"
      :loading="loading"
      border
      stripe
      @sort-change="handleSortChange"
    >
      <el-table-column
        v-if="checkFieldVisible('examNumber')"
        prop="examNumber"
        label="准考证号"
        min-width="120"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('secretNumber')"
        prop="secretNumber"
        label="密号"
        min-width="120"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('name')"
        prop="name"
        label="姓名"
        min-width="100"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('studentCode')"
        prop="studentCode"
        label="学号"
        min-width="150"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('subjectText')"
        prop="subjectText"
        label="科目"
        min-width="240"
        sortable
      >
        <template #default="{ row }">
          {{ row.subjectCode }}-{{ row.subjectName }}
        </template>
      </el-table-column>
      <el-table-column
        v-if="checkFieldVisible('paperType')"
        prop="paperType"
        label="试卷类型"
        min-width="100"
      />
      <el-table-column
        v-if="checkFieldVisible('subjectLevel')"
        prop="subjectLevel"
        label="层次"
        min-width="80"
      />
      <el-table-column
        v-if="checkFieldVisible('subjectCategory')"
        prop="subjectCategory"
        label="专业类型"
        min-width="100"
      />
      <el-table-column
        v-if="checkFieldVisible('scanStatus')"
        label="扫描识别"
        min-width="130"
      >
        <template #default="{ row }">
          <span v-if="!row.upload">未上传</span>
          <el-space v-else :size="8">
            <!-- 上传 -->
            <span v-if="appStore.isMultiExam">已上传</span>
            <el-button
              v-else
              type="primary"
              link
              style="padding-left: 0"
              @click="onPreviewImg(row)"
              >已上传</el-button
            >
            <!-- 缺考 -->
            <span>{{ row.absent ? '缺考' : '正常' }}</span>
          </el-space>
        </template>
      </el-table-column>
      <el-table-column
        v-if="checkFieldVisible('paperCount')"
        prop="sheetCount"
        label="扫描张数"
        min-width="110"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('breachText')"
        label="人工指定"
        min-width="130"
      >
        <template #default="{ row }">
          <el-space :size="8">
            <!-- 违纪 -->
            <template v-if="row.breach">
              <el-button
                v-if="userStore.isSchoolAdmin"
                type="danger"
                link
                style="padding-left: 0"
                @click="onChangeBreach(row)"
                >违纪</el-button
              >
              <span v-else>违纪</span>
            </template>
            <span v-else>正常</span>
            <!-- 人工指定缺考 -->
            <span>{{ row.manualAbsent ? '人工指定' : '正常' }}</span>
          </el-space>
        </template>
      </el-table-column>
      <el-table-column
        v-if="checkFieldVisible('batchCode')"
        prop="batchCode"
        label="批次编号"
        min-width="110"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('packageCode')"
        prop="packageCode"
        label="签到表编号"
        min-width="120"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('college')"
        prop="college"
        label="学院"
        min-width="100"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('className')"
        prop="className"
        label="班级"
        min-width="100"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('teacher')"
        prop="teacher"
        label="任课老师"
        min-width="110"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('examSite')"
        prop="examSite"
        label="考点"
        min-width="100"
        sortable
      />
      <el-table-column
        v-if="checkFieldVisible('examRoom')"
        prop="examRoom"
        label="考场"
        min-width="100"
        sortable
      />
      <el-table-column label="操作" width="120" fixed="right">
        <template v-if="userStore.isSchoolAdmin" #default="scope">
          <el-button type="primary" link @click="onEdit(scope.row)">
            修改
          </el-button>
          <el-button
            v-if="!appStore.isMultiExam"
            type="danger"
            link
            @click="onDelete(scope.row)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-model:current-page="pagination.pageNumber"
      v-model:page-size="pagination.pageSize"
      :layout="pagination.layout"
      :total="pagination.total"
      @size-change="pageSizeChange"
      @current-change="toPage"
    />
  </div>

  <!-- 新增/编辑学生弹窗 -->
  <ModifyStudent
    ref="modifyStudentRef"
    :row-data="curRow"
    @modified="getList"
  />

  <!-- 导入学生 -->
  <ImportDialog
    ref="importStudentDialogRef"
    title="导入学生"
    :upload-url="importStudentUrl"
    :format="['xls', 'xlsx']"
    :download-handle="downloadStudentTemplate"
    download-filename="学生导入模板.xlsx"
  />

  <!-- 导入名单 -->
  <ImportDialog
    ref="importAbDialogRef"
    :title="importConfig?.title"
    :upload-url="importConfig?.url"
    :format="importConfig?.format"
    :download-handle="downloadTemplate"
    :download-filename="importConfig?.donloadFilename"
  />

  <!-- 查看图片 -->
  <el-image-viewer
    v-if="showPreview"
    :url-list="curStudentSheetUrls"
    show-progress
    @close="showPreview = false"
  />
</template>

<script setup lang="ts">
  import { reactive, ref, computed, onMounted } from 'vue';
  import { CaretBottom } from '@element-plus/icons-vue';
  import { ElMessage } from 'element-plus';
  import { getExportFields, saveExportFields } from '@/api/user';
  import { getStudentList, deleteStudent, resetBreach } from '@/api/student';
  import { StudentItem, StudentListFilter } from '@/api/types/student';
  import useTable from '@/hooks/table';
  import useLoading from '@/hooks/loading';
  import { modalConfirm } from '@/utils/ui';
  import { downloadExport } from '@/utils/download-export';
  import { useAppStore, useUserStore } from '@/store';

  import ModifyStudent from './ModifyStudent.vue';

  defineOptions({
    name: 'StudentManage',
  });

  const appStore = useAppStore();
  const userStore = useUserStore();

  const searchModel = reactive<StudentListFilter>({
    name: '',
    examNumber: '',
    secretNumber: '',
    studentCode: '',
    subjectCode: '',
    subjectLevel: '',
    subjectCategory: '',
    upload: undefined,
    absent: undefined,
    manualAbsent: undefined,
    breach: undefined,
    batchCode: '',
    packageCode: '',
    college: '',
    className: '',
    teacher: '',
    examSite: '',
    examRoom: '',
    sheetCount: undefined,
  });

  const {
    dataList,
    pagination,
    loading,
    getList,
    toPage,
    pageSizeChange,
    handleSortChange,
  } = useTable<StudentItem>(getStudentList, searchModel, false);

  // 表头配置
  const tableFields = [
    { name: '准考证号', field: 'examNumber' },
    { name: '密号', field: 'secretNumber' },
    { name: '姓名', field: 'name' },
    { name: '学号', field: 'studentCode' },
    { name: '科目', field: 'subjectText' },
    { name: '试卷类型', field: 'paperType' },
    { name: '层次', field: 'subjectLevel' },
    { name: '专业类型', field: 'subjectCategory' },
    { name: '扫描识别', field: 'scanStatus' },
    { name: '扫描张数', field: 'paperCount' },
    { name: '人工指定', field: 'breachText' },
    { name: '批次编号', field: 'batchCode' },
    { name: '签到表编号', field: 'packageCode' },
    { name: '学院', field: 'college' },
    { name: '班级', field: 'className' },
    { name: '任课老师', field: 'teacher' },
    { name: '考点', field: 'examSite' },
    { name: '考场', field: 'examRoom' },
  ];
  const defaultCols = tableFields.map((item) => item.field);
  const headFields = ref(defaultCols);
  const checkFieldVisible = (field: string) => {
    return headFields.value.includes(field);
  };
  async function getExportCols() {
    const cols = await getExportFields('STUDENT');
    headFields.value = cols && cols.length ? cols : defaultCols;
  }
  async function handleFieldChange() {
    await saveExportFields({ type: 'STUDENT', cols: headFields.value });
  }

  // table action
  const curRow = ref({} as StudentItem);
  const modifyStudentRef = ref();

  function onEdit(row: StudentItem) {
    curRow.value = row;
    modifyStudentRef.value?.open();
  }

  function onAdd() {
    curRow.value = {} as StudentItem;
    modifyStudentRef.value?.open();
  }

  const { loading: breachLoading, setLoading: setBreachLoading } = useLoading();
  async function onChangeBreach(row: StudentItem) {
    if (breachLoading.value) return;
    const confirm = await modalConfirm(
      `确认要将该考生违纪重置为正常？`,
      '删除确认'
    ).catch(() => false);
    if (!confirm) return;

    try {
      setBreachLoading(true);
      await resetBreach(row.id);
      ElMessage.success('重置成功');
      getList();
    } catch (error) {
      console.log('重置失败:', error);
    } finally {
      setBreachLoading(false);
    }
  }

  // 删除
  const { loading: deleteLoading, setLoading: setDeleteLoading } = useLoading();
  async function onDelete(row: StudentItem) {
    if (deleteLoading.value) return;
    const confirm = await modalConfirm(
      `确定要删除考生"${row.name}"吗？`,
      '删除确认'
    ).catch(() => false);
    if (!confirm) return;

    try {
      setDeleteLoading(true);
      await deleteStudent(row.id);
      ElMessage.success('删除成功');
      getList();
    } catch (error) {
      console.log('删除失败:', error);
    } finally {
      setDeleteLoading(false);
    }
  }

  // 查看图片
  const showPreview = ref(false);
  const curStudentSheetUrls = ref<string[]>([]);
  function onPreviewImg(row: StudentItem) {
    showPreview.value = true;
    curStudentSheetUrls.value = row.sheetUrls || [];
  }

  // 导入学生
  const importStudentDialogRef = ref();
  const importStudentUrl = computed(() => {
    return appStore.curExam?.type === 'SCAN_IMAGE'
      ? '/api/admin/student/import'
      : '/api/admin/student/uploadImport';
  });
  function downloadStudentTemplate() {
    downloadExport(
      appStore.curExam?.type === 'SCAN_IMAGE'
        ? 'studentTemplate'
        : 'mediaStudentTemplate'
    );
  }
  function onImport() {
    importStudentDialogRef.value?.open();
  }

  // 导入名单
  const impoartConfigList = ref([
    {
      code: 'absent',
      title: '导入缺考名单',
      url: '/api/admin/student/absentImport',
      format: ['xls', 'xlsx'],
      donloadFilename: '缺考名单导入模板.xlsx',
    },
    {
      code: 'breach',
      title: '导入违纪名单',
      url: '/api/admin/student/breachImport',
      format: ['xls', 'xlsx'],
      donloadFilename: '违纪名单导入模板.xlsx',
    },
  ]);
  const importAbDialogRef = ref();
  const importData = reactive({
    importType: 'absent',
  });
  const importConfig = computed(() => {
    return impoartConfigList.value.find(
      (item) => item.code === importData.importType
    );
  });
  function downloadTemplate() {
    downloadExport(
      importData.importType === 'absent'
        ? 'absentStudentTemplate'
        : 'breachStudentTemplate'
    );
  }
  const onImportCommand = (command: string) => {
    importData.importType = command;
    importAbDialogRef.value?.open();
  };

  // 导出
  function onExport() {
    downloadExport('exportStudent', searchModel);
  }

  onMounted(async () => {
    await getExportCols();
    await toPage(1);
  });
</script>
