<template>
  <div class="rich-text-pdf-wrapper">
    <div ref="a4Paper" class="a4-paper">
      <div class="rich-content" v-html="content"></div>
    </div>
  </div>
</template>

<script>
  import html2canvas from 'html2canvas';

  export default {
    name: 'RichTextPdf',
    props: {
      content: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        loading: false
      };
    },
    methods: {
      async downloadPDF() {
        if (!this.content) {
          alert('没有可下载的内容');
          return;
        }

        this.loading = true;
        try {
          const el = this.$refs.a4Paper;
          // 将 DOM 转换为 Canvas，scale: 2 保证高清输出
          const canvas = await html2canvas(el, {
            scale: 2,
            useCORS: true, // 允许跨域图片
            backgroundColor: '#ffffff',
            logging: false
          });

          const imgW = canvas.width;
          const imgH = canvas.height;

          // A4 纸的宽度点数 (595 pt = 210mm)
          const a4WidthPt = 595;
          // 根据原图比例计算 A4 纸应有的高度点数
          const a4HeightPt = Math.round((imgH / imgW) * a4WidthPt);

          // A4 纸标准高度点数 (842 pt = 297mm)
          const pageHeightPt = 842;

          // 计算需要多少页
          const totalPages = Math.ceil(a4HeightPt / pageHeightPt);

          // 将 canvas 转为 JPEG base64 并解码为二进制字节数组
          const jpegB64 = canvas.toDataURL('image/jpeg', 0.92).split(',')[1];
          const jpegBytes = Uint8Array.from(atob(jpegB64), c => c.charCodeAt(0));

          // 调用你的底层 PDF 构建方法（已改造为支持多页）
          const pdfBytes = this._buildMultiPagePdf(jpegBytes, imgW, imgH, a4WidthPt, a4HeightPt, pageHeightPt, totalPages);

          // 触发浏览器下载
          const blob = new Blob([pdfBytes], { type: 'application/pdf' });
          const url = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = url;
          a.download = '富文本内容.pdf';
          document.body.appendChild(a);
          a.click();
          URL.revokeObjectURL(url);
          document.body.removeChild(a);

        } catch (error) {
          console.error('PDF 生成失败:', error);
          alert('PDF 下载失败，请重试！');
        } finally {
          this.loading = false;
        }
      },

      // 核心：构造内嵌 JPEG 图片的多页最小 PDF
      _buildMultiPagePdf(jpegBytes, imgW, imgH, pageW, totalImgH, pageH, pageCount) {
        const enc = s => new TextEncoder().encode(s);
        const concat = (...parts) => {
          const total = parts.reduce((n, p) => n + p.length, 0);
          const out = new Uint8Array(total);
          let off = 0;
          for (const p of parts) { out.set(p, off); off += p.length; }
          return out;
        };

        // 动态生成每一页的 Page 对象和 Contents 对象
        const pageObjects = [];
        const contentObjects = [];

        for (let i = 0; i < pageCount; i++) {
          const contentId = 3 + i * 2;      // Contents 对象 ID (从 3 开始)
          const pageId = 4 + i * 2;         // Page 对象 ID (从 4 开始)

          // 计算当前页的裁剪偏移量 (Y轴向下移动)
          const yOffset = -(i * pageH);
          // 注意：这里使用 /Do 绘制整图，但通过 cm 变换来实现视觉上的“分页裁剪”效果
          const stream = `q ${pageW} 0 0 ${totalImgH} 0 ${yOffset} cm /Im0 Do Q\n`;

          const streamEnc = enc(stream);
          contentObjects.push({
            id: contentId,
            bytes: concat(
              enc(`${contentId} 0 obj\n<< /Length ${streamEnc.length} >>\nstream\n`),
              streamEnc,
              enc('\nendstream\nendobj\n')
            )
          });

          pageObjects.push({
            id: pageId,
            bytes: concat(
              enc(`${pageId} 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${pageW} ${pageH}] /Contents ${contentId} 0 R /Resources << /XObject << /Im0 5 0 R >> >> >>\nendobj\n`)
            )
          });
        }

        // 构建 Kids 数组字符串
        const kidsStr = pageObjects.map(p => `${p.id} 0 R`).join(' ');

        // 基础对象
        const o1 = { id: 1, bytes: concat(enc('1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n')) };
        const o2 = { id: 2, bytes: concat(enc(`2 0 obj\n<< /Type /Pages /Kids [${kidsStr}] /Count ${pageCount} >>\nendobj\n`)) };

        // 图片对象 (所有页共享同一张长图)
        const o5 = {
          id: 5,
          bytes: concat(
            enc(`5 0 obj\n<< /Type /XObject /Subtype /Image /Width ${imgW} /Height ${imgH} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${jpegBytes.length} >>\nstream\n`),
            jpegBytes,
            enc('\nendstream\nendobj\n')
          )
        };

        // 组装所有对象
        const header = enc('%PDF-1.4\n');
        const allObjs = [o1, o2, ...contentObjects, ...pageObjects, o5];

        const offsets = [];
        let pos = header.length;
        const bodyParts = [];

        for (const o of allObjs) {
          offsets.push(pos);
          pos += o.bytes.length;
          bodyParts.push(o.bytes);
        }

        // 构建交叉引用表 (xref)
        const totalObjsCount = allObjs.length + 1; // 包含 0 号对象
        let xrefStr = `xref\n0 ${totalObjsCount}\n0000000000 65535 f \n`;
        for (const offset of offsets) {
          xrefStr += `${String(offset).padStart(10, '0')} 00000 n \n`;
        }
        xrefStr += `trailer\n<< /Size ${totalObjsCount} /Root 1 0 R >>\nstartxref\n${pos}\n%%EOF\n`;

        const xref = enc(xrefStr);
        return concat(header, ...bodyParts, xref);
      }
    }
  };
</script>

<style scoped>
  .rich-text-pdf-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  /* 核心：严格限制容器为 A4 纸比例 (210mm x 297mm ≈ 794px x 1123px) */
  .a4-paper {
    width: 794px;
    min-height: 1123px;
    padding: 40px;
    box-sizing: border-box;
    background: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    position: relative;
  }

  /* 重置并规范富文本内部样式 */
  .rich-content {
    font-family: "SimSun", "宋体", serif;
    font-size: 16px;
    line-height: 1.8;
    color: #333;
    word-wrap: break-word;
  }

  .rich-content p { margin: 8px 0; }

  .action-bar { margin-top: 20px; }

  .download-btn {
    padding: 10px 24px;
    background: #409eff;
    color: #fff;
    border: none;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
  }
  .download-btn:disabled { background: #a0cfff; cursor: not-allowed; }
</style>
