<template>
  <div :class="['report', { 'is-print': viewType === 'print' }]">
    <ReportCover :paper="sasPaper" :hasCompareProject="hasCompareProject" />
    <ReportCompare
      v-if="hasCompareProject && comparePapers.length && compareCourses.length"
      :scoreGap="scoreGap"
      :comparePapers="comparePapers"
      :compareCourses="compareCourses"
    />
    <ReportSummary
      v-if="sasPaper.id"
      :paper="sasPaper"
      :partNo="partNos.summary"
    />
    <ReportScore
      v-if="sasCourse.id"
      :course="sasCourse"
      :scoreGap="scoreGap"
      :partNo="partNos.score"
    />
    <ReportScoreGroup
      v-if="sasCourse.id"
      :course="sasCourse"
      :scoreGap="scoreGap"
      :partNo="partNos.scoreGroup"
    />
    <ReportQuestion
      v-if="paperQuestions.length"
      :questions="paperQuestions"
      :partNo="partNos.question"
    />
    <ReportDifficulty
      v-if="paperQuestions.length"
      :questions="paperQuestions"
      :partNo="partNos.difficulty"
    />
    <ReportDiscrimination
      v-if="paperQuestions.length"
      :questions="paperQuestions"
      :partNo="partNos.discrimination"
    />
    <ReportQuestionGroup
      v-if="sasPaper.id && paperQuestions.length"
      :questions="paperQuestions"
      :paper="sasPaper"
      :partNo="partNos.questionGroup"
    />
  </div>
</template>

<script setup lang="ts">
import {
  getPaper,
  getPaperQuestions,
  getSasPaper,
} from "@/api/paperAnalysisPage";
import {
  getPaperCompareList,
  getPaperCompareScoreList,
} from "@/api/projectCompareDetailPage";
import { getSasCourseList } from "@/api/allAnalysisPage";
import ReportCover from "./ReportCover.vue";
import ReportCompare from "./ReportCompare.vue";
import ReportSummary from "./ReportSummary.vue";
import ReportScore from "./ReportScore.vue";
import ReportScoreGroup from "./ReportScoreGroup.vue";
import ReportQuestion from "./ReportQuestion.vue";
import ReportQuestionGroup from "./ReportQuestionGroup.vue";
import ReportDifficulty from "./ReportDifficulty.vue";
import ReportDiscrimination from "./ReportDiscrimination.vue";
import { RANGE_POINT_TYPE } from "@/constants/constants";

import { SASPaper, SASQuestion, SasCourse, RangeConfig } from "@/types";
import { useRoute } from "vue-router";
import { computed, onMounted, nextTick } from "vue";
import { useMainStore } from "@/store";
const store = useMainStore();

const props = defineProps<{
  paperId: number;
  projectId: number;
  compareProjectId?: number;
  viewType: string;
}>();

const route = useRoute();

let courseId = $ref(undefined as unknown as number);
let projectId = $ref(undefined as unknown as number);
let paperId = $ref(undefined as unknown as number);
let compareProjectId = $ref(undefined as unknown as number);
let viewType = $ref("view");

let sasPaper = $ref<SASPaper>({} as SASPaper);
let sasCourse = $ref<SasCourse>({} as SasCourse);
let scoreGap = $ref(0);

let comparePapers = $ref<SASPaper[]>([]);
let compareCourses = $ref<SasCourse[]>([]);

let paperQuestions = $ref<SASQuestion[]>([]);
let partNos = $shallowRef({
  summary: "二",
  score: "三",
  scoreGroup: "四",
  question: "五",
  difficulty: "六",
  discrimination: "七",
  questionGroup: "八",
});

const hasCompareProject = computed(
  () =>
    !!compareProjectId &&
    comparePapers.length === 2 &&
    compareCourses.length === 2
);

onMounted(async () => {
  if (props.paperId) {
    projectId = props.projectId;
    paperId = props.paperId;
    compareProjectId = props.compareProjectId as number;
    viewType = props.viewType;
  } else {
    projectId = +route.params.projectId;
    paperId = +route.params.paperId;
    compareProjectId = +route.params.compareProjectId;
    viewType = route.params.viewType as string;

    if (viewType !== "frame") {
      const key = window.location.href.split("?")[1];
      if (!key) return;
      let keyVal = window.atob(key);
      let user = JSON.parse(keyVal);
      store.setUserInfo(user);
    }
  }

  await fetchData();

  await nextTick();

  commonInfoUpdate();

  if (viewType === "print") publishReady();
});

function commonInfoUpdate() {
  document.querySelectorAll(".report-page").forEach((dom, index) => {
    if (!index) return;
    let page = index + 1;
    let pageStr = index < 9 ? "0" + page : page + "";
    const footDom = dom.querySelector(".report-pfoot");
    if (footDom) {
      footDom.innerHTML = `PAGE ${pageStr}`;
    }
    const nameDom = dom.querySelector(".report-name");
    if (nameDom) {
      nameDom.innerHTML = `${sasPaper.projectName}成绩分析报告`;
    }
  });
}

function publishReady() {
  const eventEmitInterval = setInterval(function () {
    document.body.dispatchEvent(new Event("view-ready"));
  }, 25);

  document.body.addEventListener("view-ready-acknowledged", function () {
    clearInterval(eventEmitInterval);
  });
}

function numberPrecision(num: number) {
  return Math.round(num * 100) / 100;
}

async function fetchData() {
  await fetchPaper();
  await fetchSasPaper();
  await fetchPaperQuestions();
  await fetchSasCourse();

  if (compareProjectId) {
    await fetchComparePaperData();
    await fetchCompareCourseData();
  }

  if (
    compareProjectId ||
    comparePapers.length !== 2 ||
    compareCourses.length !== 2
  ) {
    partNos = {
      summary: "一",
      score: "二",
      scoreGroup: "三",
      question: "四",
      difficulty: "五",
      discrimination: "六",
      questionGroup: "七",
    };
    console.log(partNos);
  }
}

async function fetchPaper() {
  const res = await getPaper(paperId);
  courseId = res.data.courseId;
}

async function fetchPaperQuestions() {
  const res = await getPaperQuestions(paperId);
  paperQuestions = res.data.map((q) => {
    q.difficulityLevel = JSON.parse(
      <string>(<unknown>q.difficulityLevel) || "[]"
    );
    q.difficulityGroupLevel = JSON.parse(
      <string>(<unknown>q.difficulityGroupLevel) || "[]"
    );
    q.avgScore = numberPrecision(q.avgScore);
    q.stdev = numberPrecision(q.stdev);
    q.coefficient = numberPrecision(q.coefficient);
    q.difficulty = numberPrecision(q.difficulty);
    q.discrimination = numberPrecision(q.discrimination);
    return q;
  });
}

async function fetchSasPaper() {
  const res = await getSasPaper(paperId);
  res.data.difficulityLevel = JSON.parse(
    <string>(<unknown>res.data.difficulityLevel) || "[]"
  );
  res.data.discriminationLevel = JSON.parse(
    <string>(<unknown>res.data.discriminationLevel) || "[]"
  );
  sasPaper = res.data;
  scoreGap = getScoreGap(sasPaper.totalScore);

  sasPaper.avgScore = numberPrecision(sasPaper.avgScore);
  sasPaper.stdev = numberPrecision(sasPaper.stdev);
  sasPaper.coefficient = numberPrecision(sasPaper.coefficient);
  sasPaper.difficulty = numberPrecision(sasPaper.difficulty);
  sasPaper.reliability1 = numberPrecision(sasPaper.reliability1);
}

async function fetchSasCourse() {
  const res = await getSasCourseList({
    projectId,
    courseId,
  });

  sasCourse = parseSasCourse(res.data[0]);
}

function scoreTitle(rangeConfig: RangeConfig) {
  if (!rangeConfig) return false;
  if (rangeConfig.type === "ZERO") return "0-";

  return `${rangeConfig.baseScore + rangeConfig.adjustScore}(${
    RANGE_POINT_TYPE[rangeConfig.type]
  }${rangeConfig.adjustScore > 0 ? "+" : ""}${rangeConfig.adjustScore})-`;
}

async function fetchComparePaperData() {
  const res = await getPaperCompareList({
    projectIds: [compareProjectId],
    contrastProjectId: projectId,
    courseCode: sasPaper.courseCode,
  });
  comparePapers = res.data.map((v) => {
    v.avgScore = numberPrecision(v.avgScore);
    v.stdev = numberPrecision(v.stdev);
    v.coefficient = numberPrecision(v.coefficient);
    v.difficulty = numberPrecision(v.difficulty);
    v.reliability1 = numberPrecision(v.reliability1);
    return v;
  });
}

async function fetchCompareCourseData() {
  const res = await getPaperCompareScoreList({
    projectIds: [compareProjectId],
    contrastProjectId: projectId,
    courseCode: sasPaper.courseCode,
  });
  compareCourses = res.data.map((v) => {
    return parseSasCourse(v);
  });
}

function parseSasCourse(course: SasCourse) {
  course.scoreRange = Object.values(
    // eslint-disable-next-line
    JSON.parse(<string>(<unknown>course.scoreRange) || "{}")
  );
  course.rangeConfig = JSON.parse(
    <string>(<unknown>course.rangeConfig) || "0"
  ) || [
    {
      type: "ZERO",
      baseScore: 0,
      adjustScore: 0,
    },
  ];
  let acc = 0;
  if (Array.isArray(course.scoreRange))
    course.scoreRangeAcc = course.scoreRange.map((_v, i, a) => {
      acc += a[i];
      return acc;
    });
  course.scoreRangeTotal = acc;

  course.segements = [];
  const validSeg = Math.round(course.totalScore / scoreGap);
  for (let score = 0; score < validSeg; score++) {
    const row = [];
    row[0] = score * scoreGap;
    let nextScore = score + 1 > validSeg ? course.totalScore : score + 1;
    row[1] = course.scoreRange
      .slice(row[0], nextScore * scoreGap)
      .reduce((p, c) => p + c, 0);
    row[2] = numberPrecision(
      (100 * row[1]) / course.scoreRangeAcc[course.totalScore]
    );
    const endGap =
      nextScore * scoreGap - 1 >= course.totalScore
        ? course.totalScore
        : nextScore * scoreGap - 1;
    row[3] = course.scoreRangeAcc[endGap];
    row[4] = numberPrecision(
      (100 * row[3]) / course.scoreRangeAcc[course.totalScore]
    );
    course.segements.push(row);
  }
  if (validSeg * scoreGap === course.totalScore) {
    course.segements.push([
      course.totalScore,
      course.scoreRange[course.totalScore],
      course.scoreRange[course.totalScore] /
        course.scoreRangeAcc[course.totalScore],
      course.scoreRangeAcc[course.totalScore],
      100,
    ]);
  }

  course.rangeSegements = [];
  for (let i = 0; i < course.rangeConfig.length; i++) {
    const range = course.rangeConfig[i]!;
    const nextRange =
      i === course.rangeConfig.length - 1
        ? { baseScore: course.totalScore, adjustScore: 0 }
        : course.rangeConfig[i + 1];
    const row = [];
    row[0] = scoreTitle(range);
    row[1] =
      course.scoreRange
        .slice(
          range.baseScore + range.adjustScore,
          nextRange.baseScore + nextRange.adjustScore
        )
        .reduce((p, c) => p + c, 0) || 0;
    row[2] = numberPrecision((100 * row[1]) / course.scoreRangeTotal);
    row[3] =
      course.scoreRangeAcc[nextRange.baseScore + nextRange.adjustScore - 1] ||
      0;
    if (
      nextRange.baseScore + nextRange.adjustScore >=
      course.scoreRangeAcc.length
    ) {
      row[3] = course.scoreRangeAcc[course.scoreRangeAcc.length - 1];
    }
    row[4] = numberPrecision((100 * row[3]) / course.scoreRangeTotal);

    course.rangeSegements.push(row);
  }

  return course;
}

function getScoreGap(totalScore: number) {
  if (totalScore <= 150) {
    return 10;
  } else if (totalScore > 150 && totalScore <= 300) {
    return 20;
  } else if (totalScore > 300 && totalScore <= 450) {
    return 30;
  } else {
    return 50;
  }
}
</script>
