<template>
  <div class="page_report error">
    <div class="area_page">
      <div class="area_title" ref="pageTitle">
        <p>{{ examName }}</p>
        <p>
          <span>{{ subjectName }}</span
          ><span>{{ className }}</span
          ><span>错题名单</span>
        </p>
      </div>
    </div>
    <div
      class="area_page print_page"
      v-for="(pageData, pIndex) in tablePageData"
      :key="pIndex"
    >
      <template v-if="pIndex == 0">
        <div class="area_title">
          <p>{{ examName }}</p>
          <p>
            <span>{{ subjectName }}</span
            ><span>{{ className }}</span
            ><span>错题名单</span>
          </p>
        </div>
        <div class="module_jg"></div>
      </template>
      <div class="module_table">
        <template v-for="(item, index) in pageData" :key="index">
          <div
            class="module_table_tr bg_color"
            :rowIndex="index"
            :rowKey="item.rowKey"
            v-if="item.rowKey == 0"
          >
            <div class="module_table_td">{{ item.questionName }}</div>
            <div class="module_table_td">
              <span>{{ item.questionType }}</span>
              <span v-if="item.answerValue">标答:{{ item.answerValue }}</span>
              <span>满分:{{ item.questionScore }}分</span>
              <span>班均分:{{ item.averageScore }}</span>
              <span>班得分率:{{ item.scoreRate }}</span>
            </div>
          </div>
          <div
            class="module_table_tr"
            v-if="!item?.hiddenRatioStu"
            :id="`studentErrorData_${index}`"
            :rowIndex="index"
            :rowKey="item.rowKey"
          >
            <div class="module_table_td"></div>
            <div class="module_table_td">
              <p v-if="!item?.hiddenRatio">
                <span>{{ item.name }}</span
                ><span
                  >占⽐：{{ item.rate == "-" ? "-" : `${item.rate}%` }}</span
                ><span>（{{ item.studentNum }}/{{ item.studentCount }}）</span>
              </p>
              <p
                v-if="
                  item?.registrationCodeList &&
                  item?.registrationCodeList != '-' &&
                  !item?.hiddenStu
                "
              >
                {{ item?.registrationCodeList }}
              </p>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, nextTick, watch } from "vue";
import { ElMessage } from "element-plus";
import { jsPDF } from "jspdf";
import domtoimage from "dom-to-image";
// 定义数据类型
interface TableItem {
  rowKey: number | string;
  questionName?: string;
  questionType?: string;
  answerValue?: string;
  questionScore?: number | string;
  averageScore?: number | string;
  scoreRate?: number | string;
  hiddenRatioStu?: boolean;
  name?: string;
  rate?: number | string;
  studentNum?: number | string;
  studentCount?: number | string;
  registrationCodeList?: string;
  hiddenRatio?: boolean;
  hiddenStu?: boolean;
}

// 定义 Props
const props = defineProps({
  examName: {
    type: String,
    default: "",
  },
  tableData: {
    type: Array,
    default: () => [],
  },
  subjectName: {
    type: String,
    default: "",
  },
  className: {
    type: String,
    default: "",
  },
});

// 定义 Emits
const emit = defineEmits(["PdfLoadEnd"]);
const LoadData = () => {
  nextTick(() => {
    const pageTitleHeight = pageTitle.value?.offsetHeight || 60;
    titleHeight.value = pageTitleHeight + 20;
    tablePageData.value = [];
    TablePagesData(props.tableData, true);
  });
};
// Refs & 常量
const pageTitle = ref<HTMLElement | null>(null);
const titleHeight = ref(80);
const questionHeight = 30;
const lineHeight = 16;
const printPageHeight = 1205;
const tablePageData = ref<TableItem[][]>([]);

// 表格分页逻辑
const TablePagesData = (tableData: TableItem[], firstPage: boolean) => {
  let pageHeight = 0;
  if (firstPage) {
    pageHeight += titleHeight.value;
  }

  for (let i = 0; i < tableData.length; i++) {
    if (tableData[i].rowKey == 0) {
      pageHeight += questionHeight;
      if (pageHeight >= printPageHeight) {
        const newTableData = tableData.slice(0, i);
        tablePageData.value.push(newTableData);
        const nextTableData = tableData.slice(i);
        if (nextTableData.length) {
          TablePagesData(nextTableData, false);
        }
        return;
      }
    }

    let stuRowNum = 0;
    const regCodeList = tableData?.[i]?.registrationCodeList;
    if (regCodeList && regCodeList !== "-" && regCodeList !== "") {
      stuRowNum = Math.ceil(regCodeList.length / 56);
    }

    const rowNum = stuRowNum + 1;
    for (let j = 0; j < rowNum; j++) {
      let lineH = lineHeight;
      if (stuRowNum < 6) {
        // 防止 stuRowNum 为 0 时除以 0 报错
        lineH += stuRowNum > 0 ? Math.ceil(5 / stuRowNum) : 0;
      } else {
        if (j < 5) {
          lineH += 1;
        } else {
          lineH = lineHeight;
        }
      }
      const currentLineHeight = j == 0 ? 27 : lineH;
      pageHeight += currentLineHeight;

      if (pageHeight >= printPageHeight) {
        let newTableData: TableItem[] = [];
        let nextTableData: TableItem[] = [];

        if (tableData[i].rowKey == 0) {
          newTableData = tableData.slice(0, i + 1);
          nextTableData = tableData.slice(i);
          let pageLastData =
            newTableData.length > 0
              ? { ...newTableData[newTableData.length - 1] }
              : null;
          let firstData =
            nextTableData.length > 0 ? { ...nextTableData[0] } : null;

          if (pageLastData) {
            if (j == 0) {
              pageLastData.hiddenRatioStu = true;
            } else if (j == 1) {
              pageLastData.hiddenStu = true;
            } else {
              const sliceIndex = (j - 1) * 56;
              pageLastData.registrationCodeList =
                pageLastData.registrationCodeList?.slice(0, sliceIndex) || "";
            }
          }
          if (firstData) {
            if (j == 0) {
              firstData.rowKey = `0_${j}`;
            } else if (j == 1) {
              firstData.rowKey = `0_${j}`;
              firstData.hiddenRatio = true;
            } else {
              firstData.rowKey = `0_${j}`;
              firstData.hiddenRatio = true;
              const sliceIndex = (j - 1) * 56;
              firstData.registrationCodeList =
                firstData.registrationCodeList?.slice(sliceIndex) || "";
            }
          }

          if (newTableData.length) {
            newTableData.pop();
            newTableData.push(pageLastData!);
            tablePageData.value.push(newTableData);
          }
          if (nextTableData.length) {
            nextTableData.shift();
            nextTableData.unshift(firstData!);
            TablePagesData(nextTableData, false);
          }
        } else {
          newTableData = tableData.slice(0, i + 1);
          nextTableData = tableData.slice(i);
          let pageLastData =
            newTableData.length > 0
              ? { ...newTableData[newTableData.length - 1] }
              : null;
          let firstData =
            nextTableData.length > 0 ? { ...nextTableData[0] } : null;

          if (pageLastData) {
            if (j == 1) {
              pageLastData.hiddenStu = true;
            } else {
              const sliceIndex = (j - 1) * 56;
              pageLastData.registrationCodeList =
                pageLastData.registrationCodeList?.slice(0, sliceIndex) || "";
            }
          }
          if (firstData) {
            if (j == 1) {
              firstData.hiddenRatio = true;
            } else {
              firstData.hiddenRatio = true;
              const sliceIndex = (j - 1) * 56;
              firstData.registrationCodeList =
                firstData.registrationCodeList?.slice(sliceIndex) || "";
            }
          }

          if (newTableData.length) {
            newTableData.pop();
            newTableData.push(pageLastData!);
            tablePageData.value.push(newTableData);
          }
          if (nextTableData.length) {
            nextTableData.shift();
            nextTableData.unshift(firstData!);
            TablePagesData(nextTableData, false);
          }
        }
        return;
      }
    }
  }

  if (tableData.length) {
    tablePageData.value.push(tableData);
  }
};

// 下载 PDF (使用 dom-to-image)
const DownloadPdf = async () => {
  const elements = document.querySelectorAll(".page_report .print_page");
  if (elements.length === 0) {
    ElMessage.warning("未找到可导出的页面元素！");
    emit("PdfLoadEnd");
    return;
  }

  const pdf = new jsPDF("p", "pt", "a4");
  const pdfWidth = pdf.internal.pageSize.getWidth();
  const pdfHeight = pdf.internal.pageSize.getHeight();

  for (const [pageIndex, element] of Array.from(elements).entries()) {
    await nextTick();
    if (element) {
      const htmlElement = element as HTMLElement;
      htmlElement.style.visibility = "visible";
      htmlElement.offsetHeight;

      await new Promise((resolve) => setTimeout(resolve, 100));

      const dataUrl = await domtoimage.toJpeg(htmlElement, {
        quality: 0.8,
        width: htmlElement.scrollWidth * 2,
        height: htmlElement.scrollHeight * 2,
        canvasWidth: htmlElement.scrollWidth * 2,
        canvasHeight: htmlElement.scrollHeight * 2,
        style: {
          transform: "scale(2)",
          "transform-origin": "top left",
          "background-color": "#ffffff",
          overflow: "visible",
          "white-space": "normal",
          position: "relative",
          visibility: "visible",
        },
        bgcolor: "#ffffff",
      });

      const imgProps = pdf.getImageProperties(dataUrl);
      const imgWidth = imgProps.width;
      const imgHeight = imgProps.height;

      const ratio = Math.min(pdfWidth / imgWidth, pdfHeight / imgHeight);
      const adjustWidth = imgWidth * ratio;
      const adjustHeight = imgHeight * ratio;

      const xPosition = (pdfWidth - adjustWidth) / 2;
      const yPosition = (pdfHeight - adjustHeight) / 2;

      if (pageIndex > 0) {
        pdf.addPage();
      }
      pdf.addImage(
        dataUrl,
        "JPEG",
        xPosition,
        yPosition,
        adjustWidth,
        adjustHeight,
      );
    }
  }

  pdf.save(
    `${props.examName}_${props.subjectName}_${props.className}错题名单.pdf`,
  );
  emit("PdfLoadEnd");
};
// 监听筛选条件
watch(
  () => props.tableData,
  async () => {
    if (props.tableData.length) {
      LoadData();
    }
  },
  { deep: true },
);

// 暴露方法供父组件调用
defineExpose({
  DownloadPdf
});
</script>

<style lang="scss" scoped>
.error {
  width: 908px;
  margin: 0 auto;
  position: absolute;
  top: 0;
  left: -9999px;
  z-index: -10;
  .area_page {
    width: 908px;
    margin-top: 20px;
    padding: 40px !important;
    background-color: #fff;
    box-sizing: border-box;
    overflow: hidden;
    &.print_page {
      height: 1285px;
    }
    .area_title {
      font-weight: bold;
      font-size: 24px;
      color: #000000;
      line-height: 30px;
      p {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
        gap: 5px;
      }
    }
    .module_jg {
      height: 20px;
      width: 100%;
    }
    .module_table {
      width: 100%;
      border: 1px solid #ebeef5;
      box-sizing: border-box;
      background-color: #fff;
      border-radius: 6px;
      .module_table_tr {
        &.bg_color {
          background-color: #f5f7fa;
          .module_table_td {
            font-weight: 500;
            &:nth-child(2) {
              gap: 5px;
              align-items: center;
            }
          }
        }
        min-height: 30px;
        box-sizing: border-box;
        border-top: 1px solid #ebeef5;
        display: flex;
        width: 100%;
        &:first-child {
          border-top: 0;
        }
        .module_table_td {
          padding: 5px;
          box-sizing: border-box;
          border-left: 1px solid #ebeef5;
          font-size: 12px;
          font-weight: 400;
          color: #000000;
          &:first-child {
            width: 100px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border-left: 0;
          }
          &:nth-child(2) {
            flex: 1;
            display: flex;
            flex-wrap: wrap;
            p {
              line-height: 16px;
              display: flex;
              flex-wrap: wrap;
              width: 100%;
              &:first-child {
                padding-bottom: 5px;
                gap: 5px;
              }
            }
          }
        }
      }
    }
  }
}
</style>
