<template>
  <div class="mark check-paper">
    <div class="mark-header">
      <div class="mark-header-part">
        <template v-if="student">
          <div class="header-noun">
            <span>课程名称：</span>
            <span> {{ student.courseName }}（{{ student.courseCode }}）</span>
          </div>
          <div class="header-noun">
            <span>试卷编号：</span>
            <span>{{ student.paperNumber }}</span>
          </div>
          <div class="header-noun">
            <span>姓名：</span>
            <span>{{ student.studentName }}</span>
          </div>
          <div class="header-noun">
            <span>学号：</span>
            <span>{{ student?.studentCode }}</span>
          </div>
          <div v-if="studentIds.length > 1" class="header-noun">
            <span>进度：</span>
            <span> {{ currentIndex + 1 }}/{{ studentIds.length }} </span>
          </div>
        </template>
      </div>
      <div class="mark-header-part">
        <div class="paper-menu">
          <span
            v-for="(u, index) in student?.sheetUrls"
            :key="index"
            :class="{ 'is-active': currentImage === index }"
            @click="currentImage = index"
          >
            {{ index + 1 }}
          </span>
        </div>
        <div class="header-text-btn header-logout" @click="logout">
          <img class="header-icon" src="@/assets/icons/icon-return.svg" />返回
        </div>
      </div>
    </div>

    <div class="mark-main">
      <div class="mark-body">
        <div
          v-if="student && currentImage !== 0"
          class="page-action page-prev"
          title="上一张"
          @click="switchImageArrow({ left: true })"
        >
          <ArrowLeftOutlined />
        </div>
        <div
          v-if="student && currentImage !== student.sheetUrls.length - 1"
          class="page-action page-next"
          title="上一张"
          @click="switchImageArrow({ right: true })"
        >
          <ArrowRightOutlined />
        </div>
        <div class="mark-body-container">
          <div v-if="!student" class="mark-body-none">
            <div>
              <img src="@/assets/image-none-task.png" />
              <p>暂无数据</p>
            </div>
          </div>
          <div
            v-else
            class="single-image-container"
            :style="{ width: answerPaperScale, fontSize: answerPaperFontSize }"
          >
            <img
              id="mark-body-paper"
              draggable="false"
              :src="curImageUrl"
              :style="{
                transform:
                  (rotateDegree ? 'translate( 0,  calc(30vh))' : '') +
                  `rotate(${rotateDegree}deg)`,
              }"
              @click="switchImage"
              @contextmenu="showBigImage"
              @load="paperLoad"
            />
            <div
              v-for="(tag, tindex) in answerTags"
              :key="tindex"
              :style="tag.style"
            >
              {{ tag.answer }}
            </div>
            <div
              v-for="(tag, tindex) in optionsBlocks"
              :key="tindex + 'block'"
              :style="tag.style"
            ></div>
          </div>
        </div>
        <ZoomPaper v-if="student" showRotate fixed @rotateRight="rotateRight" />
      </div>

      <div class="mark-board-track">
        <div class="board-header no-action">
          <div class="board-header-info">
            <img src="@/assets/icons/icon-star.svg" />
            <span>总分</span>
          </div>
          <div class="board-header-score">
            <transition-group name="score-number-animation" tag="span">
              <span :key="totalScore">{{ totalScore }}</span>
            </transition-group>
          </div>
        </div>
        <div class="paper-topics">
          <div
            v-for="group in answersComputed"
            :key="group.mainNumber"
            class="paper-topic"
          >
            <h2 class="paper-topic-title">
              {{ group.mainNumber }}、{{ group.mainTitle }} ({{
                group.subs.length
              }})
            </h2>
            <div class="paper-topic-body">
              <div
                v-for="question in group.subs"
                :key="question.subNumber"
                class="paper-topic-question"
              >
                <span class="question-number">{{ question.subNumber }} </span>
                <a-input
                  class="normal-input"
                  :class="{
                    'long-input': question.type
                      ? !['SINGLE', 'TRUE_OR_FALSE'].includes(question.type)
                      : !group.mainTitle.match(/单选|单项|判断/),
                  }"
                  :value="question.answer"
                  :maxLength="
                    (
                      question.type
                        ? ['MULTIPLE'].includes(question.type)
                        : group.mainTitle.match(/多选|多项|不定项/)
                    )
                      ? 100
                      : 1
                  "
                  @keydown="onPreventAnswerKey"
                  @input="changeAnswer($event, question)"
                  @blur="changeAnswer($event, question, '#')"
                />
              </div>
            </div>
          </div>
        </div>

        <div :class="['board-footer', { 'is-simple': !isMultiStudent }]">
          <qm-button
            class="board-submit"
            size="medium"
            type="primary"
            :disabled="!student?.upload"
            @click="saveStudentAnswer"
          >
            保存
          </qm-button>
          <div v-if="isMultiStudent" class="student-switch">
            <a-button :disabled="isFirst" @click="getPreviousStudent">
              上一份
            </a-button>
            <a-button :disabled="isLast" @click="getNextStudent">
              下一份
            </a-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { message } from "ant-design-vue";
import { ArrowLeftOutlined, ArrowRightOutlined } from "@ant-design/icons-vue";
import { onMounted, watch } from "vue";
import "viewerjs/dist/viewer.css";
import Viewer from "viewerjs";
import { StudentObjectiveInfo, PaperRecogData, AnswerTagItem } from "@/types";

import {
  studentObjectiveConfirmData,
  saveStudentObjectiveConfirmData,
} from "@/api/checkPage";
import { doLogout } from "@/api/markPage";

import { useMarkStore } from "@/store";
import { useTimers } from "@/setups/useTimers";
import vls from "@/utils/storage";
import { maxNum } from "@/utils/utils";

import ZoomPaper from "@/components/ZoomPaper.vue";

const { addTimeout } = useTimers();

const markStore = useMarkStore();

const studentIds = $ref(vls.get("check-students", []));

onMounted(async () => {
  if (studentIds.length === 0) {
    void message.info("没有需要处理的考生，请返回。");
    return;
  }
  await getNextStudent();
});

let currentStudentId = $ref("");

const currentIndex = $computed(() => studentIds.indexOf(currentStudentId));
const isFirst = $computed(() => currentIndex === 0);
const isLast = $computed(() => currentIndex === studentIds.length - 1);
const isMultiStudent = $computed(() => studentIds.length > 1);
const totalScore = $computed(() => {
  if (!student) return 0;
  return student.objectiveScore || 0;
});

const curImageUrl = $computed(() =>
  student ? student.sheetUrls[currentImage]?.url : ""
);

let student: StudentObjectiveInfo | null = $ref(null);
/** 后台数据错误，停止整个页面的流程 */
let dataError = $ref(false);
let answerMap: Record<string, { answer: string; isRight: boolean }> = {};

let answerTags = $ref<AnswerTagItem[]>([]);
let optionsBlocks = $ref([]);

const answersComputed = $computed(() => {
  let mains = student?.answers.map((v) => ({
    mainTitle: "",
    mainNumber: v.mainNumber,
    subs: [v],
  }));
  const mSet = new Set();
  mains = mains?.filter((v) => {
    if (!mSet.has(v.mainNumber)) {
      mSet.add(v.mainNumber);
      v.subs = [];
      return true;
    }
  });
  mains?.forEach((v) => {
    v.mainTitle = student?.titles[v.mainNumber] ?? "";
    v.subs =
      student?.answers.filter((v2) => v2.mainNumber === v.mainNumber) ?? [];
  });
  return mains;
});

function logout() {
  doLogout();
}

async function getNextStudent() {
  if (isLast) {
    void message.warning("已经是最后一份！");
    return;
  }
  student = await getStudent(studentIds[currentIndex + 1]);
}

async function getPreviousStudent() {
  if (isFirst) {
    void message.warning("已经是第一份！");
    return;
  }
  student = await getStudent(studentIds[currentIndex - 1]);
}

async function getStudent(studentId: string) {
  const res = await studentObjectiveConfirmData(studentId).catch(() => {
    dataError = true;
  });
  if (dataError) {
    void message.error(res.message, 24 * 60 * 60);
    throw new Error("取学生信息出错: " + res.message);
  }

  const stu = res.data as StudentObjectiveInfo;
  // stu.sheetUrls = [
  //   { index: 1, url: "/1-1.jpg" },
  //   { index: 2, url: "/1-2.jpg" },
  // ];
  currentStudentId = stu.studentId;
  currentImage = 0;
  browsedImageIndexes = [0];

  answerMap = {};
  stu.answers.forEach((item) => {
    answerMap[`${item.mainNumber}_${item.subNumber}`] = {
      answer: item.answer,
      isRight: item.answer === item.standardAnswer,
    };
  });

  return stu;
}

const allowKey = [
  "Delete",
  "Backspace",
  "ArrowLeft",
  "ArrowRight",
  "#",
  "Shift",
  "[A-Za-z]",
];
const allowKeyRef = new RegExp(allowKey.join("|"));

function onPreventAnswerKey(e: KeyboardEvent) {
  console.log(e);
  if (!allowKeyRef.test(e.key)) {
    e.preventDefault();
  }
}

function changeAnswer(event: Event, question: string, defaultValue?: string) {
  const target = event.target as HTMLInputElement;
  student.answers = student.answers.map((v) => {
    if (
      v.mainNumber === question.mainNumber &&
      v.subNumber === question.subNumber
    ) {
      v.answer = target?.value.toUpperCase().trim() || defaultValue || "";
    }
    return v;
  });
}

let loading = false;
async function saveStudentAnswer() {
  if (!student) return;

  if (loading) return;
  loading = true;

  const data = {
    studentId: student.studentId,
    answers: student.answers.map((v) => v.answer || "#").join(","),
  };
  // if (!answers.match(/^(#*,*[A-Z]*)+$/g)) {
  //   void message.error("答案只能是#和大写英文字母");
  //   return;
  // }

  const res = await saveStudentObjectiveConfirmData(data).catch(() => false);
  loading = false;
  if (!res) {
    void message.error("保存失败，请刷新页面。");
  } else {
    void message.success("保存成功");

    if (!isMultiStudent) {
      window.close();
      return;
    }

    if (isLast) {
      student = await getStudent(studentIds[currentIndex]);
    } else {
      await getNextStudent();
    }
  }
}

function paperLoad() {
  if (!student.sheetUrls[currentImage]?.recogData) {
    answerTags = [];
    optionsBlocks = [];
    return;
  }
  const imgDom = document.getElementById("mark-body-paper");
  const { naturalWidth, naturalHeight } = imgDom;
  const recogData: PaperRecogData = JSON.parse(
    window.atob(student.sheetUrls[currentImage].recogData)
  );

  answerTags = [];
  optionsBlocks = [];
  recogData.question.forEach((question) => {
    question.fill_result.forEach((result) => {
      const tagSize = result.fill_size[1];
      const fillPositions = result.fill_position.map((pos) => {
        return pos.split(",").map((n) => n * 1);
      });

      const offsetLt = result.fill_size.map((item) => item * 0.4);
      const tagLeft =
        maxNum(fillPositions.map((pos) => pos[0])) +
        result.fill_size[0] -
        offsetLt[0];
      const tagTop = fillPositions[0][1] - offsetLt[1];

      const { answer, isRight } =
        answerMap[`${result.main_number}_${result.sub_number}`] || {};

      answerTags.push({
        mainNumber: result.main_number,
        subNumber: result.sub_number,
        answer,
        style: {
          height: ((100 * tagSize) / naturalHeight).toFixed(4) + "%",
          fontSize: ((100 * 20) / tagSize).toFixed(4) + "%",
          left: ((100 * tagLeft) / naturalWidth).toFixed(4) + "%",
          top: ((100 * tagTop) / naturalHeight).toFixed(4) + "%",
          position: "absolute",
          color: isRight ? "#05b575" : "#f53f3f",
          fontWeight: 600,
          lineHeight: 1,
          zIndex: 9,
        },
      });

      // 测试：选项框
      // fillPositions.forEach((fp, index) => {
      //   optionsBlocks.push({
      //     mainNumber: result.main_number,
      //     subNumber: result.sub_number,
      //     filled: !!result.fill_option[index],
      //     style: {
      //       width:
      //         ((100 * result.fill_size[0]) / naturalWidth).toFixed(4) + "%",
      //       height:
      //         ((100 * result.fill_size[1]) / naturalHeight).toFixed(4) + "%",
      //       left:
      //         ((100 * (fp[0] - offsetLt[0])) / naturalWidth).toFixed(4) + "%",
      //       top:
      //         ((100 * (fp[1] - offsetLt[1])) / naturalHeight).toFixed(4) + "%",
      //       position: "absolute",
      //       border: "1px solid #f53f3f",
      //       background: result.fill_option[index]
      //         ? "rgba(245, 63, 63, 0.5)"
      //         : "transparent",
      //       zIndex: 9,
      //     },
      //   });
      // });
    });
  });
}

//#region : 显示大图，供查看和翻转
let currentImage = $ref(0);
let browsedImageIndexes = $ref([0]);
// let allViewed = $computed(() => {
//   let indexes = Array.from(new Set(browsedImageIndexes));
//   return indexes.length == (student?.sheetUrls || []).length;
// });
watch(
  () => currentImage,
  () => {
    browsedImageIndexes.push(currentImage);
  }
);
function switchImageArrow({
  left = false,
  right = false,
}: {
  left?: boolean;
  right?: boolean;
}) {
  if (left) {
    if (currentImage > 0) {
      currentImage--;
    }
  }
  if (right) {
    if (currentImage < student.sheetUrls.length - 1) {
      currentImage++;
    }
  }
}

function switchImage(event: MouseEvent) {
  const image = event.target as HTMLImageElement;
  const layerX: number = (event as any).layerX;
  if (layerX * 2 < image.width) {
    if (currentImage > 0) {
      currentImage--;
    }
  } else {
    if (currentImage < student.sheetUrls.length - 1) {
      currentImage++;
    }
  }
}

const showBigImage = (event: MouseEvent) => {
  event.preventDefault();
  // console.log(event);
  let viewer: Viewer = null as unknown as Viewer;
  viewer && viewer.destroy();
  viewer = new Viewer((event.target as HTMLElement).parentElement, {
    // inline: true,
    viewed() {
      viewer.zoomTo(1);
    },
    hidden() {
      viewer.destroy();
    },
    zIndex: 1000000,
  });
  viewer.show();
};
//#endregion : 显示大图，供查看和翻转

//#region : 放大缩小和之后的滚动
const answerPaperScale = $computed(() => {
  // 放大、缩小不影响页面之前的滚动条定位
  let percentWidth = 0;
  let percentTop = 0;
  const container = document.querySelector<HTMLDivElement>(
    ".mark-body-container"
  );
  if (container) {
    const { scrollLeft, scrollTop, scrollWidth, scrollHeight } = container;
    percentWidth = scrollLeft / scrollWidth;
    percentTop = scrollTop / scrollHeight;
  }

  addTimeout(() => {
    if (container) {
      const { scrollWidth, scrollHeight } = container;
      container.scrollTo({
        left: scrollWidth * percentWidth,
        top: scrollHeight * percentTop,
      });
    }
  }, 10);
  const scale = markStore.setting.uiSetting["answer.paper.scale"];
  return scale * 100 + "%";
});
const answerPaperFontSize = $computed(() => {
  const scale = markStore.setting.uiSetting["answer.paper.scale"];
  return scale * 14 + "px";
});
//#endregion : 放大缩小和之后的滚动

//#region rotateRight
let rotateDegree = $ref(0);
function rotateRight() {
  rotateDegree = (rotateDegree + 90) % 360;
}
//#endregion
</script>
