import { Canvg } from 'canvg';
import html2canvas from 'html2canvas-pro';
import JSPDF from 'jspdf';
import { nextTick } from 'vue';

const A4_WIDTH = 595;
const A4_HEIGHT = 842;
const HEADER_HEIGHT = 16;
const FOOTER_HEIGHT = 24;
const PAGE_HEIGHT = A4_HEIGHT - FOOTER_HEIGHT - HEADER_HEIGHT;
const PDF_WIDTH = A4_WIDTH - 32; // 左右分别 16px 间距
const CONTAINER_WIDTH = 1190;
export const SCALE_RATIO = window.devicePixelRatio * 1.5;
// 实际每页高度 = PDF页面高度/页面容器宽度与 pdf 宽度的比例(这里比例*SCALE_RATIO 是因为html2canvas截图时生成的是 SCALE_RATIO 倍的清晰度)
export const IMAGE_HEIGHT = Math.ceil(PAGE_HEIGHT * (CONTAINER_WIDTH / PDF_WIDTH) * SCALE_RATIO);
export const MAX_CANVAS_HEIGHT = IMAGE_HEIGHT * 20; // 一次截图最大高度是 20 页整（过长会无法截完整，出现空白）

/**
 * 替换svg为base64
 */
async function inlineSvgUseElements(container: HTMLElement) {
  const useElements = container.querySelectorAll('use');
  useElements.forEach((useElement) => {
    const href = useElement.getAttribute('xlink:href') || useElement.getAttribute('href');
    if (href) {
      const symbolId = href.substring(1);
      const symbol = document.getElementById(symbolId);
      if (symbol) {
        const svgElement = useElement.closest('svg');
        if (svgElement) {
          svgElement.innerHTML = symbol.innerHTML;
        }
      }
    }
  });
}

/**
 * 将svg转换为base64
 */
async function convertSvgToBase64(svgElement: SVGSVGElement) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const svgString = new XMLSerializer().serializeToString(svgElement);
  if (ctx) {
    const v = Canvg.fromString(ctx, svgString);
    canvas.width = svgElement.clientWidth;
    canvas.height = svgElement.clientHeight;
    await v.render();
  }
  return canvas.toDataURL('image/png');
}

/**
 * 替换svg为base64
 */
export async function replaceSvgWithBase64(container: HTMLElement) {
  await inlineSvgUseElements(container);
  const svgElements = container.querySelectorAll('.c-icon');
  svgElements.forEach(async (svgElement) => {
    const img = new Image();
    img.src = await convertSvgToBase64(svgElement as SVGSVGElement);
    img.width = svgElement.clientWidth;
    img.height = svgElement.clientHeight;
    img.style.marginRight = '8px';
    svgElement.parentNode?.replaceChild(img, svgElement);
  });
}


/**  
 * 处理 DOM 元素的分页，防止内容被截断  
 * @param containerId 容器 ID  
 * @param pageHeight PDF 一页的有效高度 (对应你的 PAGE_HEIGHT 或 IMAGE_HEIGHT / SCALE_RATIO)  
 */  
function handlePageBreak(containerId: string, pageHeight: number) {  
  const container = document.getElementById(containerId);  
  if (!container) return;  
  
  // 获取所有直接子元素，这里假设子元素是不可分割的块（比如一行表格、一个段落）  
  // 根据实际情况，你可能需要更精确的选择器，比如 '.table-row', 'p', 'img'  
  const children = Array.from(container.children) as HTMLElement[];  
    
  let currentPageHeight = 0;  
  const nodesToMove: { node: HTMLElement; spacerHeight: number }[] = [];  
  
  children.forEach((child) => {  
    const childHeight = child.offsetHeight;  
    // 如果元素本身就比一页还高，那没法处理，只能让它截断  
    if (childHeight > pageHeight) {  
      currentPageHeight += childHeight;  
      // 重置当前页高度计数，近似处理  
      currentPageHeight = currentPageHeight % pageHeight;   
      return;  
    }  
  
    // 判断加上当前元素后是否超出一页  
    if (currentPageHeight + childHeight > pageHeight) {  
      // 计算需要插入的空白高度，把当前元素挤到下一页开头  
      const spacerHeight = pageHeight - currentPageHeight;  
      nodesToMove.push({ node: child, spacerHeight });  
      // 当前元素被挤到下一页了，所以新的当前页高度就是它自己的高度  
      currentPageHeight = childHeight;   
    } else {  
      // 没超出一页，累加高度  
      currentPageHeight += childHeight;  
    }  
  });  
  
  // 统一插入空白占位符  
  // 需要倒序插入，否则会影响后续元素的 offsetTop 计算（虽然这里用的是累加高度，倒序更安全）  
  for (let i = nodesToMove.length - 1; i >= 0; i--) {  
    const { node, spacerHeight } = nodesToMove[i];  
    const spacer = document.createElement('div');  
    spacer.style.height = `${spacerHeight}px`;  
    spacer.style.width = '100%';  
    // 标记一下，方便导出后移除  
    spacer.className = 'pdf-page-break-spacer';   
    spacer.style.backgroundColor = 'transparent'; // 确保透明  
    container.insertBefore(spacer, node);  
  }  
    
  return () => {  
    // 返回一个清理函数，在导出完成后移除这些占位符，恢复网页原样  
    const spacers = container.querySelectorAll('.pdf-page-break-spacer');  
    spacers.forEach(spacer => spacer.remove());  
  }  
}  


/**
 * 导出PDF
 * @param name 文件名
 * @param contentId 内容DOM id
 * @description 通过html2canvas生成图片，再通过jsPDF生成pdf
 * （使用html2canvas截图时，因为插件有截图极限，超出极限部分会出现截图失败，所以这里设置了MAX_CANVAS_HEIGHT截图高度，然后根据这个截图高度分页截图，然后根据每个截图裁剪每页 pdf 的图片并添加到 pdf 内）
 */
export default async function exportPDF(name: string, contentId: string, doneCallback?: () => void) {
  const element = document.getElementById(contentId);
  if (element) {
    await replaceSvgWithBase64(element);
    const totalHeight = element.scrollHeight;
    // jsPDFs实例
    const pdf = new JSPDF({
      unit: 'pt',
      format: 'a4',
      orientation: 'p',
    });
    pdf.setFontSize(10);
    // 计算pdf总页数
    let totalPages = 0;
    let position = 0; // 当前截图位置
    let pageIndex = 1;
    let loopTimes = 0;
    const screenshotList: HTMLCanvasElement[] = [];
    // 创建图片裁剪画布
    const cropCanvas = document.createElement('canvas');
    cropCanvas.width = CONTAINER_WIDTH * SCALE_RATIO; // 因为截图时放大了 SCALE_RATIO 倍，所以这里也要放大
    cropCanvas.height = IMAGE_HEIGHT;
    const tempContext = cropCanvas.getContext('2d', { willReadFrequently: true });
    // 这里是大的分页，也就是截图画布的分页
    while (position < totalHeight) {
      // 截图高度
      const screenshotHeight = Math.min(MAX_CANVAS_HEIGHT, totalHeight - position);
      // eslint-disable-next-line no-await-in-loop
      const canvas = await html2canvas(element, {
        x: 0,
        y: position,
        width: CONTAINER_WIDTH,
        height: screenshotHeight,
        backgroundColor: '#f9f9fe',
        scale: SCALE_RATIO, // 缩放增加清晰度
      });
      screenshotList.push(canvas);
      position += screenshotHeight;
      totalPages += Math.ceil(canvas.height / IMAGE_HEIGHT);
      loopTimes++;
    }
    totalPages -= loopTimes - 1; // 减去多余的页数
    // 生成 PDF
    screenshotList.forEach((_canvas) => {
      const canvasWidth = _canvas.width;
      const canvasHeight = _canvas.height;
      const pages = Math.ceil(canvasHeight / IMAGE_HEIGHT);
      for (let i = 1; i <= pages; i++) {
        // 这里是小的分页，是 pdf 的每一页
        const pagePosition = (i - 1) * IMAGE_HEIGHT;
        if (tempContext) {
          if (pageIndex === totalPages) {
            // 填充背景颜色为白色
            tempContext.fillStyle = '#ffffff';
            tempContext.fillRect(0, 0, cropCanvas.width, cropCanvas.height);
          }
          // 将大分页的画布图片裁剪成pdf 页面内容大小，并渲染到临时画布上
          tempContext.drawImage(_canvas, 0, -pagePosition, canvasWidth, canvasHeight);
          const tempCanvasData = cropCanvas.toDataURL('image/jpeg', 1);
          // 将临时画布图片渲染到 pdf 上
          pdf.addImage(tempCanvasData, 'PNG', 16, 16, PDF_WIDTH, PAGE_HEIGHT);
        }
        cropCanvas.remove();
        pdf.text(
          `${pageIndex} / ${totalPages}`,
          pdf.internal.pageSize.width / 2 - 10,
          pdf.internal.pageSize.height - 4
        );
        if (i < pages) {
          pdf.addPage();
          pageIndex++;
        }
      }
      _canvas.remove();
    });
    pdf.save(`${name}.pdf`);
    nextTick(() => {
      doneCallback?.();
    });
  }
}

