<script lang="ts" setup>
import moment from "moment";
import { ExamType, OnlineExam } from "@/types/student-client";
import { store } from "@/store/store";
import StartExamModal from "./StartExamModal.vue";
import { tryLimit } from "@/utils/tryLimit";
import { useTimers } from "@/setups/useTimers";
import { WEEKDAY_NAMES } from "@/constants/constants";
import OnlineExamResultList from "./OnlineExamResultList.vue";
import { useRoute } from "vue-router";
import { watch } from "vue";

const {
  courses = [],
  endCourses = [],
  examType = "ONLINE",
} = defineProps<{
  courses: OnlineExam[];
  endCourses: OnlineExam[];
  examType?: ExamType;
}>();

const route = useRoute();

let selectedCourse: OnlineExam | null = $ref(null);
let selectExamState: "EXAMING" | "EXAM_END" = $ref("EXAMING");

watch(route, () => {
  selectExamState = "EXAMING";
});

const selectedCourseList = $computed(() =>
  selectExamState === "EXAMING" ? courses : endCourses
);

function cycleDesc(course: OnlineExam) {
  if (!course.examCycleEnabled) {
    return "";
  }
  const weekDesc = course.examCycleWeek.map((v) => "周" + WEEKDAY_NAMES[v]);
  const timeRangeDesc = course.examCycleTimeRange
    .map((v) => v.timeRange)
    .map((v) => v[0] + "~" + v[1])
    .join("<br>");
  return weekDesc + "<br>" + timeRangeDesc;
}

function courseInBetween(course: OnlineExam) {
  return moment(store.getTimeStamp).isBetween(
    moment(course.startTime),
    moment(course.endTime)
  );
}

function disableReason(course: OnlineExam) {
  if (!courseInBetween(course)) {
    return "当前时间不在考试开放时间范围";
  } else if (course.allowExamCount < 1) {
    return "无剩余考试次数";
  } else if (!courseInCycle(course)) {
    return "不在考试时间周期内";
  } else if (buttonCountDown > 0) {
    return "请稍等";
  } else {
    return "";
  }
}

function courseInCycle(course: OnlineExam) {
  if (!course.examCycleEnabled) {
    return true;
  }
  const weekday = moment(store.getTimeStamp).isoWeekday();
  if (!course.examCycleWeek.includes(weekday)) {
    return false;
  }
  const HHmm = moment(store.getTimeStamp).format("HH:mm");
  const ranges = course.examCycleTimeRange.map((v) => v.timeRange);
  const inRange = ranges.some((v) => HHmm >= v[0] && HHmm <= v[1]);
  return inRange;
}

function disableTheCourse(course: OnlineExam) {
  return (
    !courseInBetween(course) ||
    course.allowExamCount < 1 ||
    !courseInCycle(course) ||
    buttonCountDown > 0
  );
}

const { addInterval } = useTimers();
let buttonCountDown = $ref(0);

addInterval(() => buttonCountDown--, 1000);

async function raceEnter(course: OnlineExam) {
  logger({
    cnl: ["server"],
    pgu: "AUTO",
    act: "点击进入考试按钮",
  });
  const minutesAfterCourseStart = Math.floor(
    moment(store.getTimeStamp).diff(moment(course.startTime), "seconds") / 60
  );

  store.increaseGlobalMaskCount("raceEnter");
  const { limitResult, serverOk } = await tryLimit({
    action: "startExam",
    limit: 100,
  });
  logger({
    cnl: ["server"],
    pgu: "AUTO",
    key: "开考限流API call",
  });
  store.decreaseGlobalMaskCount("raceEnter");

  if (limitResult) {
    logger({
      cnl: ["server"],
      pgu: "AUTO",
      act: "开考未限流",
      dtl: "限流-" + minutesAfterCourseStart + "分进入",
    });

    selectedCourse = course;
  } else {
    logger({
      cnl: ["server"],
      pgu: "AUTO",
      act: "开考被限流",
      dtl: "限流-" + minutesAfterCourseStart + "分被限流",
      ext: { serverOk },
    });
    $dialog.warning({
      title: "提示",
      content: "网络繁忙，请稍后再试。",
      onClose: () => {
        buttonCountDown = 3;
      },
    });
  }
}
</script>

<template>
  <div class="list">
    <div style="display: flex; margin-bottom: 10px">
      <n-button
        type="success"
        :class="selectExamState != 'EXAMING' && 'button-unselected'"
        @click="selectExamState = 'EXAMING'"
      >
        待考列表
      </n-button>
      <n-button
        v-if="examType === 'ONLINE'"
        type="success"
        :class="selectExamState != 'EXAM_END' && 'button-unselected'"
        @click="selectExamState = 'EXAM_END'"
      >
        已结束考试
      </n-button>
    </div>

    <table>
      <tbody class="list-row">
        <tr class="list-header qm-primary-strong-text">
          <td>课程</td>
          <td key="cc">层次</td>
          <td key="zy">专业</td>
          <td>考试进入时间</td>
          <td>考试时间周期</td>
          <td>剩余考试次数</td>
          <td style="max-width: 200px">操作</td>
        </tr>

        <tr
          v-for="course in selectedCourseList"
          :key="course.examId + course.courseId"
        >
          <td>{{ course.courseName }}</td>
          <td key="cc">{{ course.courseLevel }}</td>
          <td key="zy">{{ course.specialtyName }}</td>
          <td>
            {{ course.startTime }} <br />
            ~ <br />
            {{ course.endTime }}
          </td>
          <td>
            <span v-html="cycleDesc(course)" />
          </td>
          <td>{{ course.allowExamCount }}</td>
          <td style="min-width: 180px">
            <div class="tw-flex tw-flex-col" style="max-width: 200px">
              <n-button
                v-if="selectExamState == 'EXAMING'"
                type="success"
                :disabled="disableTheCourse(course)"
                :title="disableTheCourse(course) ? disableReason(course) : ''"
                @click="raceEnter(course)"
              >
                进入考试
                {{ buttonCountDown > 0 ? `(${buttonCountDown}s)` : "" }}
              </n-button>
              <div class="tw-mt-3" />
              <n-popover trigger="hover" placement="left-start" :delay="300">
                <template #trigger>
                  <n-button :disabled="!course.isObjScoreView" type="success">
                    客观分
                  </n-button>
                </template>
                <OnlineExamResultList :examStudentId="course.examStudentId" />
              </n-popover>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  <StartExamModal
    v-if="selectedCourse"
    :course="selectedCourse"
    @onUnselectCourse="selectedCourse = null"
  />
</template>

<style scoped>
.list {
  border: 1px solid #eeeeee;
  border-top: none;
  border-radius: 6px;
}

.list table {
  width: 100%;
  border-collapse: collapse !important;
  border-spacing: 0;
}
.list td {
  border: 1px solid #eeeeee;
  border-radius: 6px;
  border-collapse: separate !important;
  padding: 10px;
}
.button-unselected {
  color: #9e9f9e;
  background-color: white;
}
</style>
