<template>
  <el-dialog title="导出预览" :visible.sync="dialogVisible" width="95%" top="20px" append-to-body
    :close-on-click-modal="false" @open="generatePreviewHtml">
    <div style="display: flex; gap: 16px; height: calc(100vh - 200px);">
      <div style="width: 200px; flex-shrink: 0; border: 1px solid #e4e7ed; border-radius: 4px; padding: 12px; overflow-y: auto;">
        <div style="font-weight: bold; margin-bottom: 10px; font-size: 14px;">产品表列配置</div>
        <el-checkbox v-model="selectAllColumns" :indeterminate="columnIndeterminate" @change="handleSelectAllColumns"
          style="margin-bottom: 8px;">全选</el-checkbox>
        <div v-for="col in columnConfigs" :key="col.key" style="margin-bottom: 6px;">
          <el-checkbox v-model="col.checked" @change="onColumnChange">{{ col.label }}</el-checkbox>
        </div>
        <el-divider />
        <div style="font-weight: bold; margin-bottom: 10px; font-size: 14px;">附加行配置</div>
        <el-checkbox v-model="selectAllRows" :indeterminate="rowIndeterminate" @change="handleSelectAllRows"
          style="margin-bottom: 8px;">全选</el-checkbox>
        <div v-for="rowCfg in rowConfigs" :key="rowCfg.key" style="margin-bottom: 6px;">
          <el-checkbox v-model="rowCfg.checked" @change="onRowChange">{{ rowCfg.label }}</el-checkbox>
        </div>
      </div>
      <div style="flex: 1; border: 1px solid #e4e7ed; border-radius: 4px; overflow: hidden; background: #f0f0f0;">
        <iframe ref="previewFrame" style="width: 100%; height: 100%; border: none; background: #fff;"></iframe>
      </div>
    </div>
    <span slot="footer">
      <el-button @click="handleCancel">取 消</el-button>
      <el-button type="primary" :loading="exporting" @click="confirmExport">确认导出</el-button>
    </span>
  </el-dialog>
</template>

<script>
import contractLogo from '@/assets/images/contractLogo.png';
import {
  parseProductContent,
  convertToChinese
} from '@/utils/productContent';
import html2canvas from 'html2canvas';
import { jsPDF } from 'jspdf';

const CHINESE_HEADING_REGEX = /^[零一二三四五六七八九十百千]+、/;

export default {
  name: "ContractExportDialog",
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    row: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      exporting: false,
      selectAllColumns: true,
      columnIndeterminate: false,
      columnConfigs: [
        { key: 'spec', label: '规格（mm）', checked: true },
        { key: 'material', label: '材质', checked: true },
        { key: 'quantity', label: '数量（吨）', checked: true },
        { key: 'taxPrice', label: '含税单价（元/吨）', checked: true },
        { key: 'taxDivisor', label: '税率除数', checked: true },
        { key: 'noTaxPrice', label: '无税单价（元/吨）', checked: true },
        { key: 'taxTotal', label: '含税总额（元）', checked: true },
        { key: 'noTaxTotal', label: '无税总额（元）', checked: true },
        { key: 'taxAmount', label: '税额（元）', checked: true },
        { key: 'remark', label: '备注', checked: true },
      ],
      selectAllRows: true,
      rowIndeterminate: false,
      rowConfigs: [
        { key: 'totalRow', label: '合计行', checked: true },
        { key: 'amountWordsRow', label: '大写金额行', checked: true },
        { key: 'remarkRow', label: '备注行', checked: true },
      ],
    };
  },
  computed: {
    dialogVisible: {
      get() {
        return this.visible;
      },
      set(val) {
        this.$emit('update:visible', val);
      }
    }
  },
  methods: {
    handleCancel() {
      this.$emit('update:visible', false);
    },
    handleSelectAllColumns(val) {
      this.columnConfigs.forEach(col => { col.checked = val; });
      this.columnIndeterminate = false;
      this.generatePreviewHtml();
    },
    onColumnChange() {
      const checkedCount = this.columnConfigs.filter(c => c.checked).length;
      this.selectAllColumns = checkedCount === this.columnConfigs.length;
      this.columnIndeterminate = checkedCount > 0 && checkedCount < this.columnConfigs.length;
      this.generatePreviewHtml();
    },
    handleSelectAllRows(val) {
      this.rowConfigs.forEach(row => { row.checked = val; });
      this.rowIndeterminate = false;
      this.generatePreviewHtml();
    },
    onRowChange() {
      const checkedCount = this.rowConfigs.filter(r => r.checked).length;
      this.selectAllRows = checkedCount === this.rowConfigs.length;
      this.rowIndeterminate = checkedCount > 0 && checkedCount < this.rowConfigs.length;
      this.generatePreviewHtml();
    },
    buildProductTableHtml(productData, products) {
      const activeCols = this.columnConfigs.filter(c => c.checked);
      const activeRows = this.rowConfigs.filter(r => r.checked);
      const hasCol = (key) => activeCols.some(c => c.key === key);
      const hasRow = (key) => activeRows.some(r => r.key === key);

      let headerCells = '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:30px;">序号</th>';
      if (hasCol('spec')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:80px;">规格(mm)</th>';
      if (hasCol('material')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:60px;">材质</th>';
      if (hasCol('quantity')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:55px;">数量(吨)</th>';
      if (hasCol('taxPrice')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:70px;">含税单价(元/吨)</th>';
      if (hasCol('taxDivisor')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:45px;">税率除数</th>';
      if (hasCol('noTaxPrice')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:70px;">无税单价(元/吨)</th>';
      if (hasCol('taxTotal')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:70px;">含税总额(元)</th>';
      if (hasCol('noTaxTotal')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:70px;">无税总额(元)</th>';
      if (hasCol('taxAmount')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:55px;">税额(元)</th>';
      if (hasCol('remark')) headerCells += '<th style="border:1px solid #000;padding:4px 4px;font-weight:bold;width:80px;">备注</th>';
      const colCount = activeCols.length + 1;

      let bodyRows = '';
      products.forEach((product, index) => {
        let cells = `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${index + 1}</td>`;
        if (hasCol('spec')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${product.spec || ''}</td>`;
        if (hasCol('material')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${product.material || ''}</td>`;
        if (hasCol('quantity')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${product.quantity || ''}</td>`;
        if (hasCol('taxPrice')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${product.taxPrice || ''}</td>`;
        if (hasCol('taxDivisor')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${product.taxDivisor || '1.13'}</td>`;
        if (hasCol('noTaxPrice')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${(product.noTaxPrice || 0).toFixed(3)}</td>`;
        if (hasCol('taxTotal')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${(product.taxTotal || 0).toFixed(3)}</td>`;
        if (hasCol('noTaxTotal')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${(product.noTaxTotal || 0).toFixed(3)}</td>`;
        if (hasCol('taxAmount')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${(product.taxAmount || 0).toFixed(3)}</td>`;
        if (hasCol('remark')) cells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;max-width:100px;word-wrap:break-word;">${product.remark || ''}</td>`;
        bodyRows += `<tr>${cells}</tr>`;
      });

      const totalQty = products.reduce((a, p) => a + (parseFloat(p.quantity) || 0), 0);
      const totalTax = products.reduce((a, p) => a + (parseFloat(p.taxTotal) || 0), 0);
      const totalNoTax = products.reduce((a, p) => a + (parseFloat(p.noTaxTotal) || 0), 0);
      const totalTaxAmt = products.reduce((a, p) => a + (parseFloat(p.taxAmount) || 0), 0);
      const totalAmountInWords = productData.totalAmountInWords || convertToChinese(totalTax) || '零元整';

      let totalCells = '';
      let cellIdx = 0;
      activeCols.forEach((col) => {
        if (cellIdx < 2) {
          if (cellIdx === 0) {
            totalCells += `<td colspan="3" style="border:1px solid #000;padding:4px 4px;font-weight:bold;text-align:center;">合&nbsp;&nbsp;计</td>`;
          }
        } else {
          let val = '';
          if (col.key === 'quantity') val = totalQty.toFixed(3);
          else if (col.key === 'taxTotal') val = totalTax.toFixed(3);
          else if (col.key === 'noTaxTotal') val = totalNoTax.toFixed(3);
          else if (col.key === 'taxAmount') val = totalTaxAmt.toFixed(3);
          totalCells += `<td style="border:1px solid #000;padding:3px 4px;text-align:center;">${val}</td>`;
        }
        cellIdx++;
      });

      const html = `
        <table style="width:100%;border-collapse:collapse;font-size:11px;margin-bottom:6px;">
          <tr>
            <td colspan="4" style="border:1px solid #000;padding:3px 6px;font-weight:bold;text-align:left;">产品名称：${productData.productName || ''}</td>
            <td colspan="${colCount - 4 > 0 ? colCount - 4 : 1}" style="border:1px solid #000;padding:3px 6px;font-weight:bold;text-align:left;">生产厂家：嘉祥科伦普重工有限公司</td>
          </tr>
          <tr>${headerCells}</tr>
          ${bodyRows}
          ${hasRow('totalRow') ? `<tr>${totalCells}</tr>` : ''}
          ${hasRow('amountWordsRow') ? `<tr><td colspan="${colCount}" style="border:1px solid #000;padding:4px 6px;font-weight:bold;text-align:left;">合计人民币（大写）：${totalAmountInWords}</td></tr>` : ''}
          ${hasRow('remarkRow') && productData.remark ? `<tr><td colspan="${colCount}" style="border:1px solid #000;padding:4px 6px;text-align:left;">备注：${productData.remark}</td></tr>` : ''}
        </table>`;
      return html;
    },
    buildContractContentHtml(htmlContent) {
      if (!htmlContent) return '';

      const pTagRegex = /<p[^>]*>([\s\S]*?)<\/p>/g;
      let match;

      // Parse into clauses: each heading (Chinese number + 、) starts a new clause
      const clauses = [];
      let currentClause = null;

      while ((match = pTagRegex.exec(htmlContent)) !== null) {
        let content = match[1].replace(/<[^>]*>/g, '').replace(/&nbsp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g, '"').replace(/&#39;/g, "'").trim();
        if (!content) continue;

        const isHeading = CHINESE_HEADING_REGEX.test(content);

        if (isHeading) {
          if (currentClause) clauses.push(currentClause);
          currentClause = { heading: content, bodies: [] };
        } else if (currentClause) {
          currentClause.bodies.push(content);
        } else {
          // Content before any heading: create a headless clause
          clauses.push({ heading: null, bodies: [content] });
        }
      }
      if (currentClause) clauses.push(currentClause);

      if (clauses.length === 0) {
        // Fallback: plain text content without <p> tags
        const textContent = htmlContent.replace(/<[^>]*>/g, '').replace(/&nbsp;/g, ' ').trim();
        if (textContent) {
          clauses.push({ heading: null, bodies: [textContent] });
        }
      }

      if (clauses.length === 0) return '';

      let html = '<div style="margin-top:8px;font-size:12px;line-height:1.8;">';
      clauses.forEach(clause => {
        html += '<div data-clause style="page-break-inside:avoid;padding-top:2px;">';
        if (clause.heading) {
          html += `<div>${clause.heading}</div>`;
        }
        clause.bodies.forEach(body => {
          html += `<div>　${body}</div>`;
        });
        html += '</div>';
      });
      html += '</div>';
      return html;
    },
    generatePreviewHtml() {
      const row = this.row;
      if (!row) return;

      let productData = parseProductContent(row.productContent);
      if (!productData.productName && row.productName) {
        productData.productName = row.productName;
      }
      const products = productData.products && productData.products.length > 0 ? productData.products : [];

      const productTableHtml = this.buildProductTableHtml(productData, products);
      const contractContentHtml = this.buildContractContentHtml(row.contractContent);

      const totalTax = products.reduce((a, p) => a + (parseFloat(p.taxTotal) || 0), 0);
      const amountWords = productData.totalAmountInWords || convertToChinese(totalTax) || '零元整';

      const fullHtml = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>合同预览</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { font-family: 'SimSun','宋体',serif; color: #000; background: #e8e8e8; font-size: 12px; line-height: 1.6; display: flex; flex-direction: column; align-items: center; padding: 20px 0; }
  .a4-page { width: 794px; min-height: 1123px; padding: 30px 40px; background: #fff; margin-bottom: 20px; box-shadow: 0 2px 12px rgba(0,0,0,0.15); }
  .company-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 6px; }
  .contract-title { text-align: center; font-size: 20px; font-weight: bold; letter-spacing: 6px; margin-bottom: 14px; }
  .info-row { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 13px; line-height: 2; }
  .section-title { font-size: 13px; font-weight: bold; margin-bottom: 4px; margin-top: 8px; }
  table { width: 100%; border-collapse: collapse; }
  th, td { border: 1px solid #000; padding: 3px 4px; text-align: center; font-size: 11px; }
  th { font-weight: bold; }
  .sign-section { margin-top: 24px; font-size: 12px; line-height: 2.2; }
  .sign-section .col { width: 48%; }
  .sign-row { display: flex; justify-content: space-between; }
</style>
</head>
<body>
  <div class="a4-page" style="position:relative;">
  <img src="${contractLogo}" style="position:absolute;left:40px;top:40px;height:80px;" crossorigin="anonymous" />
  <div style="text-align:center;padding-top:10px;">
    <div style="font-size:20px;font-weight:bold;letter-spacing:2px;">嘉祥科伦普重工有限公司</div>
  </div>
   <div style="position:relative;margin:12px 0 8px 0;text-align:center;">
    <div style="font-size:22px;font-weight:bold;letter-spacing:6px;">产 品 销 售 合 同</div>
    <div style="position:absolute;right:0;top:50%;transform:translateY(-50%);font-size:11px;">合同编号：${row.contractCode || ''}</div>
  </div>
  <div class="info-row">
    <div style="width:55%;">
      <div>供方（甲方）：${row.supplier || ''}</div>
      <div>需方（乙方）：${row.customer || ''}</div>
    </div>
    <div style="width:40%;">
      <div>签订时间：${row.signTime ? this.parseTime(row.signTime, '{y}年{m}月{d}日') : ''}</div>
      <div>签订地点：${row.signLocation || ''}</div>
    </div>
  </div>
  <div class="section-title">一、产品内容</div>
  ${productTableHtml}
  ${contractContentHtml}
  <div class="sign-section" data-clause style="page-break-inside:avoid;">
    <div class="sign-row">
      <div class="col">
        <div>供方（甲方）：${row.supplier || ''}</div>
        <div>地址：${row.supplierAddress || ''}</div>
        <div>电话：${row.supplierPhone || ''}</div>
        <div>开户行：${row.supplierBank || ''}</div>
        <div>账号：${row.supplierAccount || ''}</div>
        <div>税号：${row.supplierTaxNo || ''}</div>
      </div>
      <div class="col">
        <div>需方（乙方）：${row.customer || ''}</div>
        <div>地址：${row.customerAddress || ''}</div>
        <div>电话：${row.customerPhone || ''}</div>
        <div>开户行：${row.customerBank || ''}</div>
        <div>账号：${row.customerAccount || ''}</div>
        <div>税号：${row.customerTaxNo || ''}</div>
      </div>
    </div>
  </div>
</div>
</body>
</html>`;

      this.$nextTick(() => {
        const iframe = this.$refs.previewFrame;
        if (iframe) {
          iframe.srcdoc = fullHtml;
        }
      });
    },
    getClauseCanvasPositions(iframeDoc, a4Page, canvasWidth) {
      const clauseEls = iframeDoc.querySelectorAll('[data-clause]');
      const a4Rect = a4Page.getBoundingClientRect();
      const scale = canvasWidth / a4Page.offsetWidth;

      const positions = [];
      clauseEls.forEach(el => {
        const rect = el.getBoundingClientRect();
        positions.push({
          top: (rect.top - a4Rect.top) * scale,
          bottom: (rect.bottom - a4Rect.top) * scale
        });
      });
      positions.sort((a, b) => a.top - b.top);
      return positions;
    },
    async confirmExport() {
      const iframe = this.$refs.previewFrame;
      if (!iframe || !iframe.contentWindow) return;

      const iframeDoc = iframe.contentDocument;
      const a4Page = iframeDoc.querySelector('.a4-page');
      if (!a4Page) return;

      this.exporting = true;
      try {
        const canvas = await html2canvas(a4Page, {
          scale: 2,
          useCORS: true,
          backgroundColor: '#ffffff',
          logging: false
        });

        const clausePositions = this.getClauseCanvasPositions(iframeDoc, a4Page, canvas.width);

        const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        const pW = pdf.internal.pageSize.getWidth();
        const pH = pdf.internal.pageSize.getHeight();
        const mg = 10;
        const printW = pW - mg * 2;
        const printH = pH - mg * 2;
        const ratio = canvas.width / printW;
        const pageCanvasHeight = printH * ratio;

        let currentY = 0;
        const pages = [];

        while (currentY < canvas.height) {
          let pageBottom = currentY + pageCanvasHeight;

          if (pageBottom >= canvas.height) {
            pageBottom = canvas.height;
          } else {
            for (const clause of clausePositions) {
              // If a clause starts before the page break and ends after it,
              // and the clause fits on a single page, move the break before this clause
              if (clause.top < pageBottom && clause.bottom > pageBottom) {
                if (clause.bottom - clause.top <= pageCanvasHeight) {
                  pageBottom = clause.top;
                }
                break;
              }
            }
          }

          if (pageBottom <= currentY) {
            pageBottom = currentY + pageCanvasHeight;
          }

          pages.push({ top: currentY, bottom: pageBottom });
          currentY = pageBottom;
        }

        for (let i = 0; i < pages.length; i++) {
          const { top, bottom } = pages[i];
          const sliceH = bottom - top;
          const sliceMm = sliceH / ratio;

          const sc = document.createElement('canvas');
          sc.width = canvas.width;
          sc.height = Math.ceil(sliceH);
          sc.getContext('2d').drawImage(canvas, 0, top, canvas.width, sliceH, 0, 0, canvas.width, sliceH);

          pdf.addImage(sc.toDataURL('image/jpeg', 0.95), 'JPEG', mg, mg, printW, sliceMm);

          if (i < pages.length - 1) {
            pdf.addPage();
          }
        }

        const filename = '合同_' + (this.row.contractCode || 'export') + '_' + new Date().getTime() + '.pdf';
        pdf.save(filename);
        this.$emit('update:visible', false);
      } catch (e) {
        this.$message.error('PDF导出失败：' + e.message);
        console.error(e);
      } finally {
        this.exporting = false;
      }
    },
  }
};
</script>
