<template>
  <div v-show="showSpread"
       :class="[!isFullscreen ? 'lab-designer-container' : 'lab-designer-container-fullscreen']"
       v-loading="loading" >
    <div class="header-row">
      <div class="title">
        <slot name="title"></slot>
      </div>
      <div class="unit-footer-btns">
        <el-dropdown trigger="click">
          <el-button type="primary" plain style="margin-right: 12px;">
            更多操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item @click="handleGenerate(true)">
                <div class="dropdown-item-content">
                  <el-button type="warning" plain style="margin-right: 12px;">生成续页</el-button>
                </div>
              </el-dropdown-item>
              <el-dropdown-item @click="openWingdingsDialog">
                <div class="dropdown-item-content">
                  <el-button type="info" plain style="margin-right: 12px;">插入特殊符号</el-button>
                </div>
              </el-dropdown-item>
              <el-dropdown-item @click="handleCopyRow">
                <div class="dropdown-item-content">
                  <el-button type="primary" plain style="margin-right: 12px;">复制表单</el-button>
                </div>
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-button type="success" @click="handleSave">保存</el-button>
        <BatchUploadFile @uploadImg="addPic" :colList="colListData" />
        <el-button type="primary" @click="openPdf">预览 PDF</el-button>
        <el-button type="danger" @click="close">关闭</el-button>
      </div>
    </div>
    <div v-loading="loading" ref="previewContainer" class="spread-container"></div>
  </div>
  <div v-show="showPdf" class="pdf-viewer-container" v-loading="pdfLoading" ref="pdfViewer">
    <div class="pdf-viewer-content">
      <VuePdfEmbed
        :key="pdfTimestamp"
        :height="pdfViewerHeight"
        :width="pdfContentWidth"
        :source="recordSource"
        text-layer
        :annotation-layer="false"
        @rendered="handlePdfRendered"
      />
    </div>
  </div>
  
  <!-- Wingdings 符号选择弹窗 -->
  <el-dialog
    v-model="wingdingsDialogVisible"
    title="选择特殊符号"
    width="600px"
    :close-on-click-modal="false"
  >
    <div class="wingdings-container">
      <div class="wingdings-grid">
        <div
          v-for="(item, index) in getWingdingsList"
          :key="index"
          class="wingdings-item"
          @click="selectWingdings(item)"
        >
          <span class="wingdings-symbol">{{ item.value }}</span>
          <span class="wingdings-label">{{ item.label }}</span>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="wingdingsDialogVisible = false">取消</el-button>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import '@grapecity-software/spread-sheets-designer-resources-cn'
import * as GC from '@grapecity-software/spread-sheets'
// 导入PDF导出模块
import '@grapecity-software/spread-sheets-pdf'
import VuePdfEmbed from 'vue-pdf-embed'
import 'vue-pdf-embed/dist/styles/annotationLayer.css'
import 'vue-pdf-embed/dist/styles/textLayer.css'
import * as ExcelIO from "@grapecity-software/spread-excelio"
import SpreadDesigner from '@/components/SpreadDesigner/index.vue'
import { Printer, Download, Refresh, DocumentAdd, Picture, ArrowDown } from '@element-plus/icons-vue'
import { useTagsViewStore } from '@/store/modules/tagsView'
import {
  getPDF
} from '@/api/laboratory/standard/template';
import {
  getPDFByInspectionLocal,
  getStandardTemplateInfo,
} from '@/api/pressure2/standard/template'
import {ref, onMounted,onUnmounted} from "vue";
import {InitParams} from './SpreadInterface';
import { buildFileUrl } from '@/utils'
import axios from 'axios'
import { DynamicTbApi } from '@/api/pressure2/dynamictb'
import {DynamicTbColApi} from "@/api/pressure2/dynamictbcol";
import { ExcelApi } from '@/api/pressure2/excel'
import { DynamicTbValApi } from '@/api/pressure2/dynamictbval'
import BatchUploadFile from "./BatchUploadFile.vue";
import {editReport, handleCopy, collectSheetDataSource, collectShapesIntoDataSource, serializeDataSourceForStorage} from "@/utils/reportUtil";
import Designer from '@grapecity-software/spread-sheets-designer-vue'
import { ElLoading } from "element-plus"
import {getPDF2, getPDFByInspection} from "@/api/pressure2/standard/template";
import { useDictStore } from '@/store/modules/dict'

defineOptions({ name: 'SpreadViewer' });

const props = defineProps({
  initData: {
    type: Object as PropType<InitParams>,
    default: ()=>({}),
    required: true
  },
  isFullscreen:{
    type: Boolean,
    default: false,
    required: false
  }
});

const insId=ref<string>(null);

const colListData=ref([]);
const addPic = (picData) => {
  if (previewSpread) {
    if (props.initData.refName == '红外热成像检测') {
      picData.name.sheet = previewSpread.getActiveSheet().name()
      const sheet = previewSpread.getActiveSheet()
      // 实时获取当前工作表中的图片形状数量
      const existingShapes = sheet.shapes.all()
      const pictureCount = existingShapes.length

      let x, y
      if (pictureCount === 0) {
        // 第一张图片的坐标
        x = 55
        y = 430
        sheet.shapes.addPictureShape(JSON.stringify(picData.name), picData.base, x, y, 240, 320);
        return
      } else if(pictureCount === 1){
        // 第二张及后续图片的坐标
        x = 410
        y = 430
        sheet.shapes.addPictureShape(JSON.stringify(picData.name), picData.base, x, y, 240, 320);
        return
      }
    }
    picData.name.sheet = previewSpread.getActiveSheet().name()
    previewSpread.getActiveSheet().shapes.addPictureShape(JSON.stringify(picData.name), picData.base, picData.name.x, picData.name.y, picData.name.width, picData.name.height);
  }
}
/*
watch(()=>[props.initData.templateId,props.initData.refId],([newTide,newRid],[oldTid,oldRid])=>{
  if(newTide && newRid){
    initPreview();
  }

}); */

//const route = useRoute()
// spread相关
const tagsViewStore = useTagsViewStore()
const dictStore = useDictStore()
const loading = ref(true)
const showSpread=ref(true)
const previewContainer = ref(null)
let sheetData = {};
let arrayFieldOffsetInfos = [];
const designerKey = import.meta.env.VITE_SPREADJS_DESIGNER_KEY
const nodeEnv = import.meta.env.VITE_NODE_ENV
const licenseKey = import.meta.env.VITE_SPREADJS_LICENSE_KEY
GC.Spread.Sheets.Designer.LicenseKey = designerKey
//同时对SpreadJS与ExcelIO进行授权
GC.Spread.Sheets.LicenseKey = licenseKey
// pdf相关
let previewSpread = null
const pdfLoading = ref(false);
const showPdf=ref(false);
const recordSource = ref('')
const pdfViewer = ref()
const pdfContentWidth = ref(800)
const pdfViewerHeight = ref(600)
const pdfTimestamp = ref('')

// Wingdings 弹窗相关
const wingdingsDialogVisible = ref(false)
const currentCell = ref(null)

const getWingdingsList = computed(
  () => dictStore.getDictMap['Wingdings']
)

const handlePdfRendered = () => {
  pdfLoading.value = false
}

// 获取模版详情
const fetchTemplateData = async () => {
  console.log(this)
  if(!props.initData.templateId){
    return;
  }
  const templateRes = await getStandardTemplateInfo({ id: props.initData.templateId })
  if (templateRes && templateRes.fileUrl) {
    const fileUrl = buildFileUrl(templateRes.fileUrl)
    const response = await axios.get(fileUrl, { responseType: 'blob' });
    return new Blob([response.data], { type: response.headers['content-type'] });
  }
  return;
}
const initPreview = async () => {
  const { refId, opType, templateId, enterPdfUrl, issueUrl } = props.initData;
  
  if (!refId) {
    return false;
  }
  
  // 有预生成的 PDF URL 时，跳过表格渲染直接预览 PDF
  const directPdfUrl = (enterPdfUrl || issueUrl || '').trim();
  if (opType === 1 && directPdfUrl) {
    loading.value = false;
    showSpread.value = false;
    showPdf.value = true;
    recordSource.value = buildFileUrl(directPdfUrl);
    pdfTimestamp.value = Date.now();
    console.log("使用url")
    setTimeout(() => {
      calculatePdfSize()
    }, 100)
    return;
  }
  
  loading.value = true;
  
  if (opType === 0) {
    showSpread.value = true;
    pdfLoading.value = false;
  }

  previewSpread?.destroy();
  previewSpread = new GC.Spread.Sheets.Workbook(previewContainer.value);

  const handleOpenError = (error: any) => {
    console.error('文件打开失败:', error);
    loading.value = false;
  };

  const handleCopyIfNeeded = () => {
    if (opType === 0) {
      handleCopy(previewSpread);
    }
  };

  const initCommonData = async () => {
    const res = await DynamicTbValApi.getDynamicTbInsAndValByRefId(props.initData);
    insId.value = res.dynamicTbInsRespVO.id;
    dynamicTbColRespVOList = res.dynamicTbColRespVOList;
    colListData.value = res.dynamicTbColRespVOList.filter(i => i.colValType === 4);
    return res;
  };

  if (nodeEnv === 'dev' || nodeEnv === 'hst' || nodeEnv === 'uat' || nodeEnv === 'prod') {
    try {
      // 1. 获取实例和字段数据（数据绑定留给前端处理，后端只做图片/高亮/续页处理）
      const res = await initCommonData();

      // 2. 调用后端接口获取处理好的 SJS
      const apiMethod = ExcelApi.excel;
      // const apiMethod = nodeEnv === 'dev' ? ExcelApi.process : ExcelApi.excel;
      const sjsBlob: any = await apiMethod({ templateId, refId });

      // 3. 打开 SJS 后在回调中绑定数据源
      previewSpread.open(sjsBlob, () => {
        console.log('后端处理完成，预览加载完成');
        const sheets = previewSpread.sheets;

        // 构建数据源并绑定（后端不 setDataSource，交由前端处理）
        // 后端已将 .jpg/.png 路径处理为背景图片，此处设 null 避免覆盖
        if (res.dynamicTbValRespVOList && res.dynamicTbValRespVOList.length > 0) {
          sheetData = {};
          res.dynamicTbValRespVOList.forEach(i => {
            const val = i.valValue;
            if (typeof val === 'string') {
              const trimmed = val.trim();
              // 后端已将图片路径值处理为背景图片，跳过避免文字覆盖
              if (trimmed.endsWith('.jpg') || trimmed.endsWith('.png')) {
                // sheetData[i.colCode] = null;
              } else if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
                if(i.colCode === 'Illustration'){
                  sheetData[i.colCode] = null
                }else{
                  try { sheetData[i.colCode] = JSON.parse(val); } catch { sheetData[i.colCode] = val; }
                }
              } else if (val == 'false' || val == 'true') {
                sheetData[i.colCode] = val == 'true' ? 'true' : null;
              } else {
                sheetData[i.colCode] = val;
              }
            } else {
              sheetData[i.colCode] = val;
            }
          });
        }
        let dataSource1 = new GC.Spread.Sheets.Bindings.CellBindingSource(sheetData);
        if (props.initData.dataSource) {
          dataSource1 = new GC.Spread.Sheets.Bindings.CellBindingSource(props.initData.dataSource);
        }
        sheets.forEach(sheet => sheet.setDataSource(dataSource1));

        // 表格行样式同步（数据绑定后前端处理）
        handleTableRowsAfterDataBind(sheets);

        // 续页处理
        hiddenPage().then(() => {
          if (opType === 1) {
            showSpread.value = false;
            pdfLoading.value = true;
            openPdf();
          } else {
            showPdf.value = false;
            loading.value = false;
            handleCopyIfNeeded();
          }
        });
      }, handleOpenError);
    } catch (error) {
      console.error('后端处理 Excel 失败:', error);
      loading.value = false;
    }
    return;
  }

  try {
    const blob = await fetchTemplateData();
    if (!blob) return;

    previewSpread.open(blob, async () => {
      console.log('预览加载完成');
      const sheets = previewSpread.sheets;
      
      const res = await DynamicTbValApi.getDynamicTbInsAndValByRefId(props.initData);
      insId.value = res.dynamicTbInsRespVO.id;

      if (res.dynamicTbValRespVOList && res.dynamicTbValRespVOList.length > 0) {
        sheetData = {};
        res.dynamicTbValRespVOList.forEach(i => {
          const val = i.valValue;
          if (typeof val === 'string') {
            const trimmed = val.trim();
            if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
              try {
                sheetData[i.colCode] = JSON.parse(val);
              } catch {
                sheetData[i.colCode] = val;
              }
            } else if (val == 'false' || val == 'true') {
              sheetData[i.colCode] = val == 'true' ? 'true' : null;
            } else {
              sheetData[i.colCode] = val;
            }
          } else {
            sheetData[i.colCode] = val;
          }
        });
      }

      let dataSource1 = new GC.Spread.Sheets.Bindings.CellBindingSource(sheetData);
      if (props.initData.dataSource) {
        dataSource1 = new GC.Spread.Sheets.Bindings.CellBindingSource(props.initData.dataSource);
      }
      sheets.forEach(sheet => sheet.setDataSource(dataSource1));

      dynamicTbColRespVOList = res.dynamicTbColRespVOList;
      const editCols = res.dynamicTbColRespVOList.filter(i => i.isEdit).map(i => i.colCode);
      const imgCols = res.dynamicTbColRespVOList.filter(i => i.colValType === 4).map(i => i.colCode);
      colListData.value = res.dynamicTbColRespVOList.filter(i => i.colValType === 4);

      for (const sheet of sheets) {
        await editReport(sheet, editCols, imgCols, opType);
      }
      
      handleTableRowsAfterDataBind(sheets);
      await hiddenPage();

      if (opType === 1) {
        showSpread.value = false;
        pdfLoading.value = true;
        await openPdf();
      } else {
        showPdf.value = false;
        loading.value = false;
        handleCopyIfNeeded();
      }
    }, handleOpenError);

  } catch (error) {
    console.error('预览加载失败:', error);
  }
}

let dynamicTbColRespVOList;

const openPdf = async () => {
  const formData = new FormData()
  // 在异步操作开始前捕获 opType，防止切换项目时 props.initData 被覆盖导致竞态
  const currentOpType = props.initData.opType;
  const currentManualUrl = props.initData.manualUrl;
  const rules = []
  previewSpread.sheets.forEach((sheet) => {
    sheet.conditionalFormats.getRules().forEach(rule => {
      if (rule.condition() && rule.condition().formula() == 'TRUE') {
        console.log(rule)
        rules.push({
          sheet,
          rule
        })
      }
    })
    rules.forEach(rule => {
      sheet.conditionalFormats.removeRule(rule.rule)
    })
  });
 await previewSpread.save(async function (blob) {
    formData.append('file', blob)
   let response = null
   //prod环境葡萄城pdf接口
   if (nodeEnv == 'prod') {
    // 手动拼接pdf的url，适配检验方案
     if (currentManualUrl){
       formData.append('manualUrl', currentManualUrl)
       response = await getPDFByInspection(formData)
     }else{
       response = await getPDF2(formData)
     }
   } else {
     //本地测试环境葡萄城pdf接口
     if (currentManualUrl){
      // 手动拼接pdf的url，适配检验方案
       formData.append('manualUrl', currentManualUrl)
       response = await getPDFByInspectionLocal(formData)
     }else{
       response = await getPDF2(formData)
     }
   }
    if (response) {
      const flow = new Blob([response], { type: 'application/pdf' })
      recordSource.value = window.URL.createObjectURL(flow);
      if(currentOpType==0){
        loading.value = false;
        window.open(recordSource.value, '_blank');
      }
      if(currentOpType==1){
        //showSpread.value=false;
        pdfTimestamp.value = Date.now();
        showPdf.value=true;
        pdfLoading.value=true;
        setTimeout(() => {
          calculatePdfSize()
        },100)
      }
    }

  }, (e) => {

  }, {
    includeBindingSource: true
  })
  previewSpread.sheets.forEach((sheet) => {
    rules.forEach(rule => {
      if (rule.sheet === sheet){
      sheet.conditionalFormats.addRule(rule.rule)
      }
    })
  });
}

const handleSpreadPrint = () => {
  if (!previewSpread) return
  previewSpread.print()
}

/**
 * 打开 Wingdings 符号选择弹窗
 */
const openWingdingsDialog = () => {
  if (!previewSpread) {
    ElMessage.warning('请先加载文档')
    return
  }
  
  // 获取当前选中的单元格
  const activeSheet = previewSpread.getActiveSheet()
  const selections = activeSheet.getSelections()
  
  if (!selections || selections.length === 0) {
    ElMessage.warning('请先选择一个单元格')
    return
  }
  
  // 保存当前单元格信息
  const selection = selections[0]
  currentCell.value = {
    sheet: activeSheet,
    row: selection.row,
    col: selection.col
  }
  
  wingdingsDialogVisible.value = true
}

/**
 * 选择 Wingdings 符号并插入到单元格
 */
const selectWingdings = (item) => {
  if (!currentCell.value) {
    ElMessage.error('未找到目标单元格')
    return
  }
  
  const { sheet, row, col } = currentCell.value
  const cell = sheet.getCell(row, col)
  // if (!cell.allowEditInCell()){
  //   wingdingsDialogVisible.value = false
  //   return;
  // }
  // 获取当前单元格的值
  const currentValue = cell.value() || ''
  
  // 追加符号到单元格
  const newValue = currentValue + item.value
  cell.value(newValue)
  
  ElMessage.success(`已插入符号: ${item.label}`)
  wingdingsDialogVisible.value = false
}

const handleSave = () => {
  loading.value = true;
  let dataSource = {};

  const allSheetsData = []
  previewSpread.sheets.forEach((sheet) => {
    if (sheet.name() && sheet.name() !== '试用版警告') {
      const sheetData = collectSheetDataSource(sheet);
      const pageNo = getPageNoFromSheet(sheet);
      allSheetsData.push({ pageNo, data: sheetData, sheet });
    }
  });

  let copyRangePathSet = new Set();
  const hasContinuationPages = allSheetsData.some(({ pageNo }) => pageNo > 1);
  let pageNoBindingPath = null
  if (hasContinuationPages && generateData && generateData.copyRange) {
    const rangeInfo = getCopyRangeInfo();
    const templateSheet = previewSpread.getSheetFromName(generateData.sheetName);
    if (templateSheet && rangeInfo) {
      getCopyRangeBindingPaths(templateSheet, rangeInfo).forEach(p => copyRangePathSet.add(p));
      pageNoBindingPath = templateSheet.getBindingPath(rangeInfo.row, rangeInfo.col)
    }
  }

  for (const { pageNo, data, sheet } of allSheetsData) {
    for (const key in data) {
      if (pageNo > 1 && key === pageNoBindingPath) continue
      if (arrayFieldOffsetInfos.some(oi => key.startsWith(oi.prefix + '_'))) continue
      if (hasContinuationPages && copyRangePathSet.has(key)) {
        if (!dataSource[key]) {
          dataSource[key] = [];
        }
        if (Array.isArray(dataSource[key])) {
          while (dataSource[key].length < pageNo) {
            dataSource[key].push(null);
          }
          dataSource[key][pageNo - 1] = data[key];
        }
      } else if (hasContinuationPages && Array.isArray(sheetData?.[key]) && !arrayFieldOffsetInfos.some(oi => key === oi.prefix)) {
        if (!dataSource[key]) {
          dataSource[key] = [];
        }
        if (Array.isArray(data[key])) {
          dataSource[key] = dataSource[key].concat(data[key]);
        }
      } else {
        if (!dataSource.hasOwnProperty(key) && data[key] != null) {
          dataSource[key] = data[key];
        }
      }
    }
    collectShapesIntoDataSource(sheet, dataSource);
  }

  for (const oi of arrayFieldOffsetInfos) {
    const { prefix, fields } = oi
    const copyMinIndex = Math.min(...fields.map(f => f.index))
    const copyFieldNames = new Set(fields.map(f => f.path))
    const result = []
    const templateSheetData = allSheetsData.find(s => s.sheet.name() === generateData.sheetName)
    if (templateSheetData) {
      for (let i = 1; i < copyMinIndex; i++) {
        const fieldName = `${prefix}_${i}`
        if (!copyFieldNames.has(fieldName)) {
          const val = templateSheetData.data[fieldName]
          if (val != null) {
            result.push(Array.isArray(val) ? val[0] || null : val)
          } else {
            result.push(null)
          }
        }
      }
    }
    for (const { data, sheet } of allSheetsData) {
      if (sheet.name() !== generateData.sheetName && !sheet.name().startsWith(generateData.sheetName + ' (')) continue
      for (const f of fields) {
        result.push(data[f.path] != null ? data[f.path] : null)
      }
    }
    dataSource[`${prefix}_1`] = result
  }

  if (Object.keys(dataSource).length > 0) {
    const serializedData = serializeDataSourceForStorage(dataSource);
    console.log(serializedData);

    DynamicTbValApi.saveAllColValue(insId.value, serializedData).then(res => {
      if (res) {
        ElMessage.success('保存成功')
        emit('saveSuccess', {insId:insId.value,dataSource:serializedData,refId:props.initData.refId});
      } else{
        ElMessage.error('保存失败')
        emit('saveFail');
      }
    }).catch(e => {
      ElMessage.error('保存失败')
      emit('saveFail');
    }).finally(() => {
      loading.value = false;
    });
  } else {
    loading.value = false;
  }
}

const distributePageDataSources = () => {
  if (!generateData || !generateData.copyRange) return
  previewSpread.sheets.forEach((sheet) => {
    if (sheet.name() && sheet.name() !== '试用版警告' && sheet.name() !== generateData.sheetName) {
      const pageNo = getPageNoFromSheet(sheet)
      if (pageNo > 1 && sheetData && Object.keys(sheetData).length > 0) {
        const pageData = buildPageDataSource(sheetData, pageNo)
        const dataSource = new GC.Spread.Sheets.Bindings.CellBindingSource(pageData)
        sheet.setDataSource(dataSource)
      }
    }
  })
}




const handleCopyRow = () => {
  if (!previewSpread) return ElMessage.warning('请先加载文档')
  const activeSheet = previewSpread.getActiveSheet()
  const selections = activeSheet.getSelections()
  if (!selections || selections.length === 0) return ElMessage.warning('请先选择一个单元格')

  const { row, col } = selections[0]

  // 找到包含当前单元格的 table
  const tables = activeSheet.tables?.all() || []
  let targetTable = null
  for (const table of tables) {
    const range = table.range()
    if (row >= range.row && row < range.row + range.rowCount && col >= range.col && col < range.col + range.colCount) {
      targetTable = table
      break
    }
  }
  if (!targetTable) return ElMessage.warning('当前单元格不在表格内，请选中表格内的单元格')

  const range = targetTable.range()
  if (row < range.row + 1) return ElMessage.warning('请选中表格内的数据行')

  // 绑定源中追加空行，让 table 自动扩展一行
  const dataSource = activeSheet.getDataSource()
  const sourceData = dataSource?.getSource()
  const bindingPath = targetTable.bindingPath()
  if (!bindingPath || !sourceData?.[bindingPath] || !Array.isArray(sourceData[bindingPath])) {
    return ElMessage.warning('表格未绑定数据源')
  }

  // 在刷新数据源前，先收集第一行的合并规则（刷新时会清空）
  const { col: tableCol, colCount: tableColCount } = range
  const firstRowSpans = collectFirstRowSpans(activeSheet, range.row + 1, tableCol, tableColCount)
  // 记录新行位置（当前 rowCount 就是新增行的索引偏移）
  const newRowIndex = range.row + range.rowCount

  // 在绑定数组中追加空对象
  sourceData[bindingPath].push({})
  activeSheet.setDataSource(null)
  activeSheet.setDataSource(dataSource)

  // 复制样式/行高/合并到新行
  previewSpread.suspendPaint()
  try {
    const copyOps = GC.Spread.Sheets.CopyToOptions.style | GC.Spread.Sheets.CopyToOptions.formula
    activeSheet.copyTo(row, tableCol, newRowIndex, tableCol, 1, tableColCount, copyOps)
    activeSheet.setRowHeight(newRowIndex, activeSheet.getRowHeight(row))
    if (firstRowSpans.length > 0) {
      applyMergeRules(activeSheet, newRowIndex, firstRowSpans)
    }
  } finally {
    previewSpread.resumePaint()
  }
  ElMessage.success('已复制行')
}

const close = () => {
  emit('close')
}

const getPageNoFromSheet = (sheet) => {
  const tag = sheet.tag()
  if (tag !== undefined && tag !== null && tag !== '' && !isNaN(parseInt(tag))) {
    return parseInt(tag)
  }
  const name = sheet.name()
  const match = name.match(/\((\d+)\)\s*$/)
  if (match) {
    return parseInt(match[1])
  }
  return 1
}

const getCopyRangeInfo = () => {
  if (!generateData || !generateData.copyRange) return null
  const col = parseInt(generateData.copyRange.topLeft.split(',')[0])
  const row = parseInt(generateData.copyRange.topLeft.split(',')[1])
  const colCount = parseInt(generateData.copyRange.topRight.split(',')[0]) - col
  const rowCount = parseInt(generateData.copyRange.bottomLeft.split(',')[1]) - row
  return { col, row, colCount, rowCount }
}

const getCopyRangeBindingPaths = (sheet, rangeInfo) => {
  if (!sheet || !rangeInfo) return []
  const { col, row, colCount, rowCount } = rangeInfo
  const paths = []
  for (let i = 0; i <= colCount; i++) {
    for (let j = 0; j <= rowCount; j++) {
      const bindingPath = sheet.getBindingPath(row + j, col + i)
      if (bindingPath) {
        paths.push(bindingPath)
      }
    }
  }
  return paths
}

const buildPageDataSource = (baseData, pageNo) => {
  if (!generateData || !generateData.copyRange) return baseData
  const rangeInfo = getCopyRangeInfo()
  if (!rangeInfo) return baseData
  const sheet = previewSpread.getSheetFromName(generateData.sheetName)
  if (!sheet) return baseData
  const pageData = { ...baseData }
  const bindingPaths = getCopyRangeBindingPaths(sheet, rangeInfo)
  const bindingPathSet = new Set(bindingPaths)
  for (const path of bindingPaths) {
    const val = baseData[path]
    if (Array.isArray(val)) {
      pageData[path] = val[pageNo - 1] !== undefined ? val[pageNo - 1] : null
    } else if (pageNo > 1) {
      pageData[path] = null
    }
  }
  const rowsPerPage = rangeInfo.rowCount + 1
  for (const key in baseData) {
    if (bindingPathSet.has(key)) continue
    const val = baseData[key]
    if (Array.isArray(val)) {
      const start = (pageNo - 1) * rowsPerPage
      pageData[key] = val.slice(start, start + rowsPerPage)
    }
  }
  for (const oi of arrayFieldOffsetInfos) {
    const { fullArray, fields } = oi
    const copyMinIndex = Math.min(...fields.map(f => f.index))
    const start = (copyMinIndex - 1) + (pageNo - 1) * oi.rowsPerPage
    let firstIdx = -1, lastIdx = -1
    let firstVal = undefined
    for (const f of fields) {
      const idx = start + (f.index - copyMinIndex)
      if (firstIdx === -1) { firstIdx = idx; firstVal = idx < fullArray.length ? fullArray[idx] : null }
      lastIdx = idx
      pageData[f.path] = idx < fullArray.length ? fullArray[idx] : null
    }
    console.log(`[buildPageDataSource] pageNo=${pageNo}, prefix=${oi.prefix}, start=${start}, idxRange=[${firstIdx},${lastIdx}], firstIdxVal=${JSON.stringify(firstVal)}, fullArrayLen=${fullArray.length}, copyMinIndex=${copyMinIndex}, rowsPerPage=${oi.rowsPerPage}`)
  }
  return pageData
}

const distributeArrayFieldToCells = () => {
  if (!generateData || !generateData.copyRange) {
    console.log('[distributeArrayFieldToCells] 跳过: generateData/copyRange 为空')
    return
  }
  if (!sheetData || !Object.keys(sheetData).length) {
    console.log('[distributeArrayFieldToCells] 跳过: sheetData 为空')
    return
  }
  const rangeInfo = getCopyRangeInfo()
  if (!rangeInfo) {
    console.log('[distributeArrayFieldToCells] 跳过: rangeInfo 为空')
    return
  }
  const baseSheet = previewSpread.getSheetFromName(generateData.sheetName)
  if (!baseSheet) {
    console.log('[distributeArrayFieldToCells] 跳过: 找不到基础 sheet')
    return
  }

  const pattern = /^(.+)_(\d+)$/
  const prefixGroups = {}
  for (let r = 0; r <= rangeInfo.rowCount; r++) {
    for (let c = 0; c <= rangeInfo.colCount; c++) {
      const bp = baseSheet.getBindingPath(rangeInfo.row + r, rangeInfo.col + c)
      if (bp) {
        const match = bp.match(pattern)
        if (match) {
          const pfx = match[1]
          if (!prefixGroups[pfx]) prefixGroups[pfx] = []
          prefixGroups[pfx].push({
            path: bp, prefix: pfx, index: parseInt(match[2]), rowInRange: r, col: c
          })
        }
      }
    }
  }

  console.log('[distributeArrayFieldToCells] copyRange 扫描到的前缀组:', Object.keys(prefixGroups))

  arrayFieldOffsetInfos = []
  const prefixSet = new Set()

  for (const pfx of Object.keys(prefixGroups)) {
    const fields = prefixGroups[pfx]
    let fullArray = null
    for (let i = 0; i <= 1000; i++) {
      const candidate = `${pfx}_${i}`
      const val = sheetData[candidate]
      if (Array.isArray(val) && val.length > 0) {
        fullArray = val
        break
      }
    }
    if (!fullArray) {
      console.log(`[distributeArrayFieldToCells] 前缀 "${pfx}" 未找到数组字段`)
      continue
    }

    for (let i = 0; i < fullArray.length; i++) {
      const key = `${pfx}_${i + 1}`
      sheetData[key] = fullArray[i]
    }

    arrayFieldOffsetInfos.push({ prefix: pfx, fullArray, rowsPerPage: rangeInfo.rowCount + 1, fields })
    prefixSet.add(pfx)
    console.log(`[distributeArrayFieldToCells] 前缀 "${pfx}" 成功: 数组长度=${fullArray.length}, rowsPerPage=${rangeInfo.rowCount}, copyRange 字段数=${fields.length}`)
  }

  if (arrayFieldOffsetInfos.length === 0) {
    console.log('[distributeArrayFieldToCells] 无有效数组，结束')
    return
  }

  previewSpread.suspendPaint()
  try {
    const copyStartRow = rangeInfo.row
    const copyRangeRowSet = new Set()
    for (let r = 0; r < rangeInfo.rowCount; r++) {
      copyRangeRowSet.add(copyStartRow + r)
    }
    for (const oi of arrayFieldOffsetInfos) {
      for (const f of oi.fields) {
        const idx = f.index - 1
        const cellRow = copyStartRow + f.rowInRange
        if (idx < oi.fullArray.length) {
          baseSheet.setValue(cellRow, rangeInfo.col + f.col, oi.fullArray[idx])
        }
      }
    }
    for (let r = 0; r < baseSheet.getRowCount(); r++) {
      if (copyRangeRowSet.has(r)) continue
      for (let c = 0; c < baseSheet.getColumnCount(); c++) {
        const bp = baseSheet.getBindingPath(r, c)
        if (bp) {
          const match = bp.match(pattern)
          if (match && prefixSet.has(match[1])) {
            const idx = parseInt(match[2]) - 1
            const oi = arrayFieldOffsetInfos.find(o => o.prefix === match[1])
            if (oi && idx < oi.fullArray.length) {
              baseSheet.setValue(r, c, oi.fullArray[idx])
            }
          }
        }
      }
    }

    const baseDS = baseSheet.getDataSource()
    if (baseDS && baseDS.rT) {
      for (const oi of arrayFieldOffsetInfos) {
        oi.fullArray.forEach((val, idx) => {
          baseDS.rT[`${oi.prefix}_${idx + 1}`] = val
        })
      }
    }
  } finally {
    previewSpread.resumePaint()
  }
}

const adjustBaseSheetArrays = () => {
  if (!generateData || !generateData.copyRange || !sheetData || !Object.keys(sheetData).length) return
  const rangeInfo = getCopyRangeInfo()
  if (!rangeInfo) return
  const baseSheet = previewSpread.getSheetFromName(generateData.sheetName)
  if (!baseSheet) return
  const bindingPaths = getCopyRangeBindingPaths(baseSheet, rangeInfo)
  const bindingPathSet = new Set(bindingPaths)
  const rowsPerPage = rangeInfo.rowCount + 1
  previewSpread.suspendPaint()
  try {
    for (let row = 0; row < baseSheet.getRowCount(); row++) {
      for (let col = 0; col < baseSheet.getColumnCount(); col++) {
        const bp = baseSheet.getBindingPath(row, col)
        if (bp && !bindingPathSet.has(bp) && Array.isArray(sheetData[bp])) {
          const val = baseSheet.getValue(row, col)
          if (Array.isArray(val)) {
            baseSheet.setValue(row, col, val.slice(0, rowsPerPage))
          }
        }
      }
    }
  } finally {
    previewSpread.resumePaint()
  }
}

const setPageNoToSheet = (sheet, pageNo, rangeInfo) => {
  if (!rangeInfo) return
  sheet.tag(String(pageNo))
}

let generateData
let sheetNum = ref(2)
/**
 * 生成续页
 * @param {boolean} isSetTimeout 是否设置定时器
 */
const handleGenerate = async (isSetTimeout) => {
  if (!generateData || !generateData.sheetName){
    ElMessage.error('请配置模板续页名称')
    return
  }
  /**
   * 生成续页
   * @param isAdd 是否继续生成
   */
  const generate = async (isAdd) => {

    const sheet = previewSpread.getSheetFromName(generateData.sheetName)
    if (!sheet.visible()) {
      sheet.visible(true)
    }
    console.log('生成续页',generateData.sheetName + " (" + sheetNum.value + ")");
      
    previewSpread.commandManager().execute({
      cmd: "copySheet",
      sheetName: generateData.sheetName,
      targetIndex: 999,
      newName: generateData.sheetName + " (" + sheetNum.value + ")",
      includeBindingSource: true
    });
    // 范围内的字段叠加
    let col = parseInt(generateData.copyRange.topLeft.split(',')[0])
    let row = parseInt(generateData.copyRange.topLeft.split(',')[1])
    let colCount = parseInt(generateData.copyRange.topRight.split(',')[0]) - col
    let rowCount = parseInt(generateData.copyRange.bottomLeft.split(',')[1]) - row
    const sheet2 = previewSpread.getSheetFromName(generateData.sheetName + " (" + sheetNum.value + ")")
    const rangeInfo = getCopyRangeInfo()
    const pageNo = sheetNum.value
    sheetNum.value = sheetNum.value + 1
    // 先设页码（tag 持久化），后续 dataSource 会覆盖左上角单元格为正确数据
    setPageNoToSheet(sheet2, pageNo, rangeInfo)
    // 解绑 copySheet 带来的旧数据源，再绑定新数据源，防止旧数据覆盖新值
    if (sheet2) {
      sheet2.setDataSource(null)
    }
    if (sheet2 && sheetData && Object.keys(sheetData).length > 0) {
      const pageData = buildPageDataSource(sheetData, pageNo)
      const dataSource = new GC.Spread.Sheets.Bindings.CellBindingSource(pageData)
      sheet2.setDataSource(dataSource)

      // 验证：读取续页 copyRange 第一行和最后一行实际单元格值
      if (rangeInfo) {
        const firstRowVals = []
        const lastRowVals = []
        for (let c = 0; c <= rangeInfo.colCount; c++) {
          const bp = sheet2.getBindingPath(rangeInfo.row, rangeInfo.col + c)
          const firstVal = sheet2.getValue(rangeInfo.row, rangeInfo.col + c)
          const lastVal = sheet2.getValue(rangeInfo.row + rangeInfo.rowCount, rangeInfo.col + c)
          firstRowVals.push(`${bp || '?'}=${JSON.stringify(firstVal)}`)
          lastRowVals.push(`${bp || '?'}=${JSON.stringify(lastVal)}`)
        }
        console.log(`[generate] pageNo=${pageNo} 续页第一行:`, firstRowVals.join(' | '))
        console.log(`[generate] pageNo=${pageNo} 续页最后行:`, lastRowVals.join(' | '))
      }
    }
    if (isAdd){
      let col = parseInt(generateData.copyRange.topLeft.split(',')[0])
      let row = parseInt(generateData.copyRange.topLeft.split(',')[1])
      let colCount = parseInt(generateData.copyRange.topRight.split(',')[0]) - col
      let rowCount = parseInt(generateData.copyRange.bottomLeft.split(',')[1]) - row
      if (!sheet2) {
        return;
      }
      if (generateData.hidden) {
        let isEmpty = true;
        for (let i = 0; i <= colCount; i++) {
          if (i === 0) continue
          const range = sheet2.getCell(row, col + i)
          if (range.value()) {
            isEmpty = false;
            break;
          }
        }
        if (isEmpty) {
          sheet2.visible(false)
        }
      }
      let isNotEmpty = false;
      for (let i = 0; i <= colCount; i++) {
        const range = sheet2.getCell(row + rowCount, col + i)
        if (range.value()) {
          isNotEmpty = true;
          break;
        }
      }
      console.log(`[generate] pageNo=${pageNo} 单元格检测 isNotEmpty=${isNotEmpty} (检查最后行 row=${row + rowCount}, 列范围=[${col},${col + colCount}])`)

      if (!isNotEmpty && arrayFieldOffsetInfos.length > 0) {
        for (const oi of arrayFieldOffsetInfos) {
          const copyMinIndex = Math.min(...oi.fields.map(f => f.index))
          const usedSoFar = (copyMinIndex - 1) + pageNo * oi.rowsPerPage
          console.log(`[generate] 续页检查 pageNo=${pageNo}, prefix=${oi.prefix}, usedSoFar=${usedSoFar}, fullArrayLen=${oi.fullArray.length}, 是否需续页=${oi.fullArray.length > usedSoFar}`)
          if (oi.fullArray.length > usedSoFar) {
            isNotEmpty = true
            break
          }
        }
      }

      if (isNotEmpty) {
        await generate(true)
      }
    }
  }

  if (isSetTimeout) {
    const loading = ElLoading.service({text: '正在生成中'})
    setTimeout(async () => {
      try {
        await generate(false)
      } finally {
        loading.close()
      }
    }, 20)
  } else {
    const loading = ElLoading.service({text: '生成续页中，数据量较大'})
    await generate(true)
    loading.close()
  }
}
/**
 * 隐藏续页
 */
const hiddenPage = async () => {
  sheetNum.value = 2
  const data = await DynamicTbApi.getDynamicTb(props.initData.templateId)

  if (data && data.copyConfig) {
    generateData = data.copyConfig
    if (!generateData.isContinuePage){
      return
    }
  } else {
    return
  }
  // 计算坐标
  let col = parseInt(generateData.copyRange.topLeft.split(',')[0])
  let row = parseInt(generateData.copyRange.topLeft.split(',')[1])
  let colCount = parseInt(generateData.copyRange.topRight.split(',')[0]) - col
  let rowCount = parseInt(generateData.copyRange.bottomLeft.split(',')[1]) - row

  distributeArrayFieldToCells()

  const sheet = previewSpread.getSheetFromName(generateData.sheetName)
  if (!sheet) {
    return;
  }
  if (generateData.hidden) {
    let isEmpty = true;
    for (let i = 0; i <= colCount; i++) {
      if (i === 0) continue
      const range = sheet.getCell(row, col + i)
      if (range.value()) {
        isEmpty = false;
        break;
      }
    }
    if (isEmpty) {
      sheet.visible(false)
    }
  }
  let isNotEmpty = false;
  for (let i = 0; i <= colCount; i++) {
    const range = sheet.getCell(row + rowCount, col + i)
    if (range.value()) {
      isNotEmpty = true;
      break;
    }
  }

  console.log('[hiddenPage] 单元格检测 isNotEmpty:', isNotEmpty, '| arrayFieldOffsetInfos:', arrayFieldOffsetInfos.length)

  if (arrayFieldOffsetInfos.length > 0) {
    for (const oi of arrayFieldOffsetInfos) {
      const copyMinIndex = Math.min(...oi.fields.map(f => f.index))
      const usedOnPage1 = (copyMinIndex - 1) + oi.rowsPerPage
      console.log(`[hiddenPage] 前缀=${oi.prefix}, 数组长度=${oi.fullArray.length}, copyMinIndex=${copyMinIndex}, rowsPerPage=${oi.rowsPerPage}, usedOnPage1=${usedOnPage1}`)
      if (oi.fullArray.length > usedOnPage1) {
        isNotEmpty = true
        break
      }
    }
  }

  console.log('[hiddenPage] 最终 isNotEmpty:', isNotEmpty)

  if (isNotEmpty) {
    await handleGenerate(false)
    adjustBaseSheetArrays()
  } else {
    distributePageDataSources()
  }
}
/**
 * 获取数据
 */
const getData = () => {
  let dataSource = {};
  previewSpread.sheets.forEach((sheet) => {
    const sheetData = collectSheetDataSource(sheet);
    for (const key in sheetData) {
      if (dataSource[key] && sheetData[key] == sheetData[key]) {
      } else {
        dataSource[key] = sheetData[key];
      }
    }
    collectShapesIntoDataSource(sheet, dataSource);
  });
  return dataSource;
}

/**
 * 数据绑定后同步表格样式——将第一行（模板行）的合并规则、样式、行高复制到所有自动扩展的数据行
 * 参考 SpreadDesigner 的 handleSheetTableCopyToOptimized
 */
const copyOptions = GC.Spread.Sheets.CopyToOptions.style | GC.Spread.Sheets.CopyToOptions.formula

const handleTableRowsAfterDataBind = (sheets) => {
  previewSpread.suspendPaint()
  try {
    for (const sheet of sheets) {
      const tables = sheet.tables?.all() || []
      for (const table of tables) {
        const range = table.range()
        const { row, rowCount, col, colCount } = range
        if (rowCount <= 1) continue

        // 批量设置自动换行
        sheet.getRange(row, col, rowCount, colCount).wordWrap(true)

        // 表格内所有单元格设为可编辑
        sheet.getRange(row, col, rowCount, colCount).allowEditInCell(true)
        sheet.getRange(row, col, rowCount, colCount).locked(false)

        // 收集第一行的合并规则
        const firstRowSpans = collectFirstRowSpans(sheet, row, col, colCount)

        // 复制样式+行高 并 应用合并
        const firstRowHeight = sheet.getRowHeight(row)
        for (let r = 1; r < rowCount; r++) {
          const currentRow = row + r
          // 复制第一行样式和公式到当前数据行
          sheet.copyTo(row, col, currentRow, col, 1, colCount, copyOptions)
          // 复制行高
          sheet.setRowHeight(currentRow, firstRowHeight)
          // 应用合并规则
          if (firstRowSpans.length > 0) {
            applyMergeRules(sheet, currentRow, firstRowSpans)
          }
        }
      }
    }
  } finally {
    previewSpread.resumePaint()
  }
}

/** 收集第一行(模板行)的合并单元格规则 */
const collectFirstRowSpans = (sheet, row, col, colCount) => {
  const firstRowSpans = []
  for (let c = col; c < col + colCount; c++) {
    const span = sheet.getSpan(row, c)
    if (span && span.row === row) {
      firstRowSpans.push({ startCol: span.col, colCount: span.colCount })
      c += span.colCount - 1
    }
  }

  // 如果没有预置合并单元格，根据第一行内容自动识别（相邻同值列合并）
  if (firstRowSpans.length === 0) {
    const firstRowValues = []
    for (let c = col; c < col + colCount; c++) {
      firstRowValues.push(sheet.getValue(row, c))
    }
    let startMergeCol = 0
    for (let c = 1; c <= colCount; c++) {
      if (c === colCount || firstRowValues[c] !== firstRowValues[c - 1]) {
        if (c - startMergeCol > 1) {
          const startCol = col + startMergeCol
          const mergeColCount = c - startMergeCol
          firstRowSpans.push({ startCol, colCount: mergeColCount })
          sheet.addSpan(row, startCol, 1, mergeColCount)
        }
        startMergeCol = c
      }
    }
  }

  return firstRowSpans
}

/** 将合并规则应用到指定行（直接按模板列的 span 结构合并，不做内容相等校验） */
const applyMergeRules = (sheet, currentRow, firstRowSpans) => {
  firstRowSpans.forEach((mergeInfo) => {
    try {
      sheet.addSpan(currentRow, mergeInfo.startCol, 1, mergeInfo.colCount)
    } catch (error) {
      // 忽略合并失败
    }
  })
}

defineExpose({reloadView:initPreview, handleSave, getWorkbook: () => previewSpread,getData});

const emit = defineEmits(['saveSuccess','docReady','docCreate','saveFail','close'])

// 动态计算PDF查看器尺寸
const calculatePdfSize = () => {
  pdfContentWidth.value = pdfViewer.value.clientWidth - 45
  pdfViewerHeight.value = pdfViewer.value.clientHeight
  console.log('props.pdfUrl', pdfContentWidth.value, pdfViewerHeight.value)
}

onMounted(() => {

  window.addEventListener('resize', calculatePdfSize)

  console.log("SpreadViewer,onMounted:"+JSON.stringify(props.initData));
  //initPreview();

})

onUnmounted(()=>{
  window.removeEventListener('resize', calculatePdfSize)
  previewSpread?.destroy();
})

</script>
<style lang="scss" scoped>
:deep(.default-toolbar) {
  padding-top: 0;
}

.lab-designer-container {
  position: relative;
  display: flex;
  flex-direction: column;

  align-items: stretch;
  /*height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 140px);*/
  height: calc(100vh - var(--top-tool-height) - 5px );
  .spread-designer-container {
    width: calc(100% - 440px);
    height: 100%;
    padding: 0;
  }
}

.lab-designer-container-fullscreen {
  position: relative;
  display: flex;
  flex-direction: column;

  align-items: stretch;
  /*height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 140px);*/
  height: 100%;
  .spread-designer-container {
    width: calc(100% - 440px);
    height: 100%;
    padding: 0;
  }
}

.header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0px 20px 16px 20px;
  background: #fff;
  border-bottom: 1px solid #e8e8e8;
}

.header-row .title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.unit-footer-btns {
  align-items: center;
}

.dropdown-item-content {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  width: 100%;
}

.spread-container {
  flex: 1;
  background: #f5f7fa;
  overflow: auto;
  padding: 0;
}
.pdf-viewer-container {
  width: 100%;
  height: calc(100% - 40px);
  //background-color: #8E8E9D;
  padding: 5px;
  box-sizing: border-box;
  overflow-y: auto;
}
.pdf-viewer-content {
  display: flex;
  justify-content: center;
  align-items: center;
}

// Wingdings 符号选择样式
.wingdings-container {
  max-height: 500px;
  overflow-y: auto;
}

.wingdings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 12px;
  padding: 10px;
}

.wingdings-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px 8px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  
  &:hover {
    border-color: #409eff;
    background-color: #ecf5ff;
    transform: translateY(-2px);
    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  }
}

.wingdings-symbol {
  font-size: 24px;
  margin-bottom: 4px;
  color: #303133;
}

.wingdings-label {
  font-size: 12px;
  color: #909399;
  text-align: center;
  word-break: break-all;
}


</style>
