<script setup lang="ts">
import RemainTime from "./RemainTime.vue";
import OverallProgress from "./OverallProgress.vue";
import QuestionFilters from "./QuestionFilters.vue";
import QuestionView from "./QuestionView.vue";
import ArrowNavView from "./ArrowNavView.vue";
import QuestionNavView from "./QuestionNavView.vue";
import FaceTracking from "./FaceTracking.vue";
import FaceId from "./FaceId.vue";
// import FaceMotion from "./FaceMotion/FaceMotion";
import FaceRecognition from "../FaceRecognition.vue";
import { STRICT_CHECK_HOSTS } from "@/constants/constants";
import { httpApp } from "@/plugins/axiosApp";
import { useTimers } from "@/setups/useTimers";
import { checkMainExe } from "@/utils/nativeMethods";
import { showLogout } from "@/utils/utils";
import { onBeforeUpdate, onMounted, onUnmounted, watch, reactive } from "vue";
import { useRoute } from "vue-router";
import { store } from "@/store/store";
import { useRemoteAppChecker } from "@/features/UserLogin/useRemoteAppChecker";
import { useScreenTop } from "./setups/useScreenTop";
import { useFaceLive } from "./setups/useFaceLive";
import { useFaceCompare } from "./setups/useFaceCompare";
import { initExamData } from "./setups/useInitExamData";
import { useWXSocket } from "./setups/useWXSocket";
import { useAnswerQuestions } from "./setups/useAnswerQuestions";
import { useRealSubmitPaper } from "./setups/useSubmitPaper";
import { Store } from "@/types/student-client";
import { closeMediaStream } from "@/utils/camera";

// 清除过时考试数据
store.exam = {} as Store["exam"];
store.exam.compareResultMap = new Map();

const { addTimeout, addInterval } = useTimers();

const answerAllQuestions = useAnswerQuestions();

let loading = $ref(true);
let usedExamTimes = reactive({
  usedExamSeconds: 0,
  startTimestamp: Date.now(),
});
const route = useRoute();
const examId = +route.params.examId;
const examRecordDataId = +route.params.examRecordDataId;
store.exam.examId = examId;
store.exam.examRecordDataId = examRecordDataId;

//#region 人脸抓拍与活体检测
let { snapId, doSnap, showSnapResult } = useFaceCompare();
let { showFaceId } = useFaceLive(doSnap);

useScreenTop(examRecordDataId);
useWXSocket();
const { userSubmitPaper, realSubmitPaper } = useRealSubmitPaper(
  examId,
  examRecordDataId,
  doSnap
);

async function userClickSubmit() {
  store.increaseGlobalMaskCount("userClickSubmit");
  void userSubmitPaper(usedExamTimes);
  // 一定要在这里等待，不然用户快速双击就会点两次
  await new Promise((res) => setTimeout(res, 1000));
  store.decreaseGlobalMaskCount("userClickSubmit");
}

onBeforeUpdate(() => {
  _hmt.push(["_trackEvent", "答题页面", "题目切换"]);
  void answerAllQuestions();
});

watch(
  () => [route.params, store.exam.examQuestionList],
  () => {
    if (!store.exam.examQuestionList) return;
    const q = store.exam.examQuestionList.find(
      (eq) => eq.order === +route.params.order
    );
    store.exam.currentQuestion = q!;
  }
);

// computed: {
//   ...mapState([
//     "uploadModalVisible",
//   ]),
// },

// beforeDestroy() {
//   this.updateExamState({
//     pictureAnswer: {},
//   });
//   // 避免macos上下塘动。避免产生滚动条。
//   document.body.classList.toggle("hide-body-scroll", false);
// },

onMounted(async () => {
  logger({
    cnl: ["server", "local"],
    pgn: "答题页面",
    act: "进入答题页面-created",
    pgu: "AUTO",
  });

  try {
    await initExamData(examId, examRecordDataId);
    loading = false;
  } catch (error) {
    logger({
      cnl: ["server"],
      pgn: "答题页面",
      act: "获取考试和试卷信息失败，退出登录",
    });
    showLogout("获取考试和试卷信息失败，退出登录");
    return;
  }

  logger({
    cnl: ["server"],
    pgu: "AUTO",
    act: "考试开始",
    dtl: "数据初始化完成",
  });
});

/** 开始作答 */
function onStartAnswer({
  usedExamSeconds: n = 0,
}: {
  usedExamSeconds: number;
}) {
  usedExamTimes.usedExamSeconds = n;
  usedExamTimes.startTimestamp = Date.now();
}

type CompareResult = { hasError: boolean; fileName: string };
function onCompareResult({ hasError, fileName }: CompareResult) {
  if (hasError) {
    // 60秒后重试抓拍
    addTimeout(() => {
      logger({
        cnl: ["server", "console"],
        pgn: "答题页面",
        act: "上次抓拍失败后重试抓拍",
      });
      doSnap();
    }, 60 * 1000);
  } else {
    store.exam.compareResultMap.set(fileName, false);
    void showSnapResult(fileName, examRecordDataId);
  }
}
//#endregion 人脸抓拍与活体检测

onUnmounted(() => {
  /** TODO: 摄像头关闭条件需要跟考试信息解耦 */
  if (store.exam.faceCheckEnabled) {
    // debug级别备选。因为初期上线，摄像头比较容易出错，所以保留此日志
    logger({
      cnl: ["server", "console"],
      pgn: "答题页面",
      act: "关闭sharedtream",
    });
    closeMediaStream();
  }
});

//#region 提交答案与交卷
// 10秒检查是否有更改需要提交答案
addInterval(() => answerAllQuestions(), 5 * 1000);

function shouldSubmitPaper() {
  logger({ cnl: ["server"], act: "时间到自动交卷" });
  void realSubmitPaper();
}
//#endregion 提交答案与交卷

//#region 页面加载失败
let pageLoadTimeout = $ref(false);
addTimeout(() => (pageLoadTimeout = true), 30 * 1000);

function reloadPage() {
  logger({
    cnl: ["server", "local"],
    pgn: "答题页面",
    act: "点击重试按钮",
    dtl: "答题页面加载失败",
  });
  window.location.reload();
}
//#endregion 页面加载失败

//#region 防作弊检查
watch(
  () => store.exam.isExceededSwitchCount,
  () => {
    logger({ cnl: ["server"], act: "切屏超出次数自动交卷" });
    void realSubmitPaper();
  }
);

addTimeout(() => {
  if (STRICT_CHECK_HOSTS.includes(window.location.hostname)) {
    if (!checkMainExe()) {
      void httpApp.post("/api/ecs_oe_student/client/exam/process/discipline");
      logger({ cnl: ["server"], act: "答题页面discipline" });
    }
  }
}, 60 * 1000);

const {
  disableLoginBtnBecauseRemoteApp: disableExamingBecauseRemoteApp,
  checkRemoteAppTxt: checkRemoteApp,
} = useRemoteAppChecker();

function checkRemoteAppClicked() {
  logger({ cnl: ["server"], pgu: "AUTO", act: "点击确认已关闭远程桌面软件" });
  void checkRemoteApp();
}

// 3分钟检测是否有远程桌面软件在运行
addInterval(() => checkRemoteApp(), 3 * 60 * 1000);
//#endregion 防作弊检查

const userInfo = $computed(
  () => store.user.displayName + " - " + store.user.studentCodeList.join(",")
);
</script>

<template>
  <div v-if="!loading" class="container">
    <div class="header">
      <RemainTime
        @onEndtime="shouldSubmitPaper"
        @onStartAnswer="onStartAnswer"
      ></RemainTime>
      <div class="tw-flex tw-flex-wrap tw-justify-between">
        <div>{{ store.exam.courseName }}</div>
        <OverallProgress></OverallProgress>
      </div>
      <div
        :style="{
          whiteSpace: userInfo.length >= 23 ? 'normal' : 'nowrap',
        }"
      >
        {{ userInfo }}
      </div>
      <QuestionFilters></QuestionFilters>
      <n-button type="success" @click="userClickSubmit">交卷</n-button>
    </div>
    <div id="examing-home-question" class="main">
      <QuestionView />
      <ArrowNavView />
    </div>
    <div class="side">
      <div class="question-nav">
        <QuestionNavView />
      </div>
      <div v-if="store.exam.faceCheckEnabled" class="camera">
        <FaceRecognition
          width="400"
          height="300"
          :showRecognizeButton="false"
          :examRecordDataId="examRecordDataId"
          :snapId="snapId"
          @onAsyncRecognizeResult="onCompareResult"
        />
      </div>
    </div>
    <FaceId v-if="showFaceId" @closeFaceid="showFaceId = false" />
    <FaceTracking v-if="store.exam.faceCheckEnabled" />
    <div
      v-if="disableExamingBecauseRemoteApp"
      style="
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        background-color: rgba(77, 77, 77, 0.95);
        z-index: 100;
        position: absolute;
      "
    >
      <div
        class="tw-flex tw-flex-col tw-justify-center tw-items-center tw-text-center tw-h-full"
      >
        <h3 class="tw-my-8 tw-text-2xl">请关闭远程桌面软件后再进行考试！</h3>
        <n-button type="success" @click="checkRemoteAppClicked">
          确认已关闭远程桌面软件
        </n-button>
      </div>
    </div>
  </div>
  <div v-else class="tw-text-center tw-my-4 tw-text-lg">
    正在等待数据返回...
    <br />
    <n-button v-if="pageLoadTimeout" type="success" @click="reloadPage">
      重试
    </n-button>
  </div>
</template>

<style scoped>
.container {
  display: grid;
  grid-template-areas:
    "header header"
    "main side";
  grid-template-rows: minmax(60px, 60px) minmax(0, 1fr);
  grid-template-columns: 1fr 400px;

  height: 100vh;
  /* width: 100vw; */
}

.header {
  display: grid;
  align-items: center;
  justify-items: center;
  grid-template-columns: minmax(100px, 200px) minmax(200px, 500px) 1fr 300px 100px;
  grid-area: header;
  background-color: #f5f5f5;
}

.main {
  display: grid;
  grid-area: main;
  grid-template-rows: 1fr 50px;
}

.side {
  display: grid;
  grid-area: side;
  grid-template-rows: 1fr;
  background-color: #f5f5f5;
}

.question-nav {
  overflow-y: scroll;
}

.camera {
  z-index: 100;
  height: 300px;
}

@media screen and (max-height: 768px) {
  .container {
    grid-template-rows: 50px minmax(0, 1fr);
  }
  .header {
    height: 50px;
  }
}

@media screen and (max-width: 960px) {
  .header {
    overflow-x: auto;
  }
}
</style>

<style>
#examing-home-question img {
  max-width: 100%;
  height: auto !important;
}

.hide-body-scroll {
  overflow: hidden !important;
}
</style>
