<!-- 预约附件代码 -->
<template>
  <div class="uploadContainer">
    <CardOne title="材料信息">
      <template #headerRight>
        <div style="margin-top: 20px">
          <el-button type="primary" :loading="downloading" @click="handleBatchDownloadSelected">
            {{ downloading ? '正在打包中...' : '下载材料包' }}
          </el-button>

          <div v-if="downloading" style="margin-top: 10px">
            <el-progress :percentage="progressPercentage" :format="progressFormat" />
            <div style="font-size: 12px; color: #666; margin-top: 5px">
              已处理文件：{{ currentCount }} / {{ totalCount }}
            </div>
          </div>
        </div>
        <!-- <div>
          <el-button @click="downloadFile" type="primary" :loading="downLoading"
            >下载材料包</el-button
          >
        </div> -->
      </template>
      <template #content>
        <el-table v-loading="loading" :data="fileTableList" boder>
          <el-table-column label="序号" type="index" width="55" />
          <el-table-column label="资料人" align="center" prop="dataPerson" width="200">
            <template #default="scope">
              <dict-tag :options="fetchDictData('oss_data_person')" :value="scope.row.dataPerson" />
            </template>
          </el-table-column>

          <el-table-column label="资料类型" align="center" prop="dataType" width="200">
            <template #default="scope">
              <dict-tag :options="fetchDictData('oss_data_type')" :value="scope.row.dataType" />
            </template>
          </el-table-column>
          <el-table-column label="注意事项" align="center" prop="precautions" />
          <el-table-column
            label="上传状态"
            align="center"
            prop="status"
            v-if="fileTableList.length > 0 && fileTableList[0].relObjectMaterialBizId"
          >
            <template #default="scope">
              <span v-if="scope.row.status === 'YSC'">已上传</span>
              <span v-if="scope.row.status === 'WSC'" style="color: red">待上传</span>
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            align="center"
            width="180"
            class-name="small-padding fixed-width"
            fixed="right"
          >
            <template #default="scope">
              <el-button
                type="primary"
                link
                @click="handleUploadFile(scope.row)"
                v-if="scope.row.status == 'WSC'"
              >
                上传
              </el-button>
              <el-button
                v-if="props.pageSource !== 'policyList' && scope.row.status == 'YSC'"
                type="primary"
                link
                @click="handleUpdate(scope.row)"
                >查看</el-button
              >
              <!-- <el-button
                v-if="props.pageSource !== 'policyList'"
                type="danger"
                link
                @click="handleDetele(scope.row)"
                >删除</el-button
              > -->
            </template>
          </el-table-column>
        </el-table>
      </template>
    </CardOne>

    <CommonDialog
      dialogTitle="上传附件"
      cancleText="取消"
      confirmText="确认"
      dialogWidth="70%"
      :openDialog="editVisible"
      @close="editVisible = false"
      @confirm="handleSubmitUpload"
      :showClose="true"
    >
      <div class="dialogBox">
        <div class="dialogLeft">
          <div class="fileUploadBox">
            <el-upload
              :action="uploadImgUrl"
              :data="{ projectBizId: userStore.projectInfo.projectBizId }"
              :headers="headers"
              multiple
              :limit="limit"
              :accept="acceptUploadType"
              :show-file-list="false"
              :on-exceed="handleExceed"
              :on-success="uploadSuccess"
              :before-upload="handleBeforeUpload"
              ref="uploadRef"
            >
              <div class="uploadBox">
                <el-icon size="20"><DocumentAdd /></el-icon>
                <div class="file">选择文件</div>
              </div>
            </el-upload>
          </div>
          <div class="tip">(支持PDF,图片格式)</div>
        </div>
        <div class="dialogRight">
          <div
            v-if="uploadedFiles.length === 0"
            style="color: #999; padding: 20px; text-align: center"
          >
            暂无上传文件
          </div>
          <el-scrollbar max-height="300px">
            <div
              v-for="(file, index) in uploadedFiles"
              :key="file.fileBizId"
              class="uploaded-file-item"
            >
              <div class="fileNameBox">{{ file.originalName }}</div>
              <div>
                <el-button type="primary" size="small" link @click="previewFile(file)">
                  查看
                </el-button>
                <el-button type="danger" size="small" link @click="removeUploadedFile(file, index)">
                  删除
                </el-button>
              </div>

              <!-- <el-icon color="red" size="18" @click="removeUploadedFile(file, index)"
                ><Delete
              /></el-icon> -->
            </div>
          </el-scrollbar>
        </div>
      </div>
    </CommonDialog>

    <!-- 文件预览弹窗 -->
    <FilePreview ref="filePreviewRef" />
  </div>
</template>

<script setup name="FileUpload">
import { ref, nextTick, shallowRef } from 'vue'
import { ElMessage } from 'element-plus'
import { downloadFilesAsZip } from '@/utils/zipDownload' // 引入刚才封装的工具
import CommonDialog from '@/components/commonDialog'
import FilePreview from '@/components/Preview/filePreview.vue'
import CardOne from '@/components/formCard/cardOne'
import { getToken } from '@/utils/auth'
import { addFile, getAppointmentFile, delFile, editAppointmentFile } from '@/api/sign/appointment'
import useDictStore from '@/store/modules/dict'
import useUserStore from '@/store/modules/user'
import { ArrowLeft, ArrowRight, ZoomIn, ZoomOut, Document, Loading } from '@element-plus/icons-vue'
const userStore = useUserStore()
import {
  uploadMaterialList,
  delUploadFile,
  uploadRelObjectMaterialList,
  uploadOssFileList,
  uploadOssFileSubmit,
  downloadCompressedFile,
  delMaterial
} from '@/api/common'
import * as PDFJS from 'pdfjs-dist'

PDFJS.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.mjs'
const props = defineProps({
  activeName: { type: String, default: '' }, //tab名称
  idsObj: { type: Object, default: () => ({}) }, //父组件传递过来的id对象
  pageSource: { type: String, default: '' } //页面来源
})
const filePreviewRef = ref(null)
// 在定义其他响应式变量的附近添加
const pdfLoading = ref(false) // PDF 加载状态
const acceptUploadType = ref('.pdf,.jpg,.jpeg,.png,.bmp,.gif,.svg')
const uploadRef = ref(null)
const dictStore = useDictStore() //获取字典数据
const { proxy } = getCurrentInstance()
const editVisible = ref(false)
const loading = ref(true)
const total = ref(0)
const fileTableList = ref([])
const limit = ref(10)
const fileSize = ref(10)
const headers = ref({ Authorization: 'Bearer ' + getToken() })
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + '/oss/api/oss/upload') // 上传的服务器地址

// 在需要预览文件的地方调用（例如原来的 previewFile 函数）
function previewFile(file) {
  // 确保传入对象包含 url 和 name 属性
  filePreviewRef.value?.open({
    url: file.url || file.fileUrl,
    name: file.originalName || file.name
  })
}
const downLoading = ref(false)
const data = reactive({
  form: {},
  queryParams: {
    objectType: 'appointment'
  }
})

// 下载材料包
// 状态管理
const downloading = ref(false)
const currentCount = ref(0)
const totalCount = ref(0)
const viewFile = file => {
  console.log('====================================')
  console.log('file', file)
  console.log('====================================')
}
const progressPercentage = computed(() => {
  if (totalCount.value === 0) return 0
  return Math.floor((currentCount.value / totalCount.value) * 100)
})

const progressFormat = percentage => `${currentCount.value}/${totalCount.value}`

// 2. 核心处理方法
const handleBatchDownloadSelected = async () => {
  let apiMaterialDtoList = []
  if (!props.idsObj.appointmentBizId) {
    apiMaterialDtoList = fileTableList.value.map(item => {
      return {
        dataPerson: item.dataPerson, //资料人（字典）
        dataPersonName: item.dataPersonName, //资料人（字典）
        dataType: item.dataType, //资料类型（字典）
        dataTypeName: item.dataTypeName, //资料类型（字典）
        fileUrlList: item.fileBizIdList.map(item2 => ({
          fileUrl: item2.url,
          fileName: item2.originalName
        }))
      }
    })
  } else {
    apiMaterialDtoList = fileTableList.value.map(item => {
      return {
        dataPerson: item.dataPerson, //资料人（字典）
        dataPersonName: item.dataPersonName, //资料人（字典）
        dataType: item.dataType, //资料类型（字典）
        dataTypeName: item.dataTypeName, //资料类型（字典）
        fileUrlList: item.fileUrlList
      }
    })
  }
  if (!apiMaterialDtoList || apiMaterialDtoList.length === 0) {
    ElMessage.warning('没有要下载的材料')
    return
  }

  // --- 步骤 1: 数据清洗与扁平化 ---
  const flatFileList = []
  let hasFiles = false
  apiMaterialDtoList.forEach((item, index) => {
    // 安全检查：确保 fileUrlList 存在且是数组
    const urls = item.fileUrlList
    if (!urls || !Array.isArray(urls) || urls.length === 0) {
      return // 跳过没有文件的行
    }

    hasFiles = true

    // 生成安全的业务前缀
    // 规则：[人员类型]_[资料类型]_[业务ID]
    // 例如：POLICYHOLDER_FRONT_2216
    const safePerson = (item.dataPersonName || 'UNKNOWN').replace(/[\/\\:*?"<>|]/g, '_')
    const safeType = (item.dataTypeName || 'FILE').replace(/[\/\\:*?"<>|]/g, '_')

    const filePrefix = `${safePerson}_${safeType}`

    urls.forEach((fileItem, fIndex) => {
      // 兼容 fileUrlList 可能是字符串数组 或 对象数组
      let fileUrl = fileItem.fileUrl
      let originalFileName = fileItem.fileName

      // --- 关键：构建最终文件名 ---

      const finalFileName = `${filePrefix}_${originalFileName}`

      if (fileUrl) {
        flatFileList.push({
          url: fileUrl,
          name: finalFileName,
          // 可选：保留元数据用于调试
          _meta: {
            type: item.dataType,
            note: item.precautions
          }
        })
      }
    })
  })

  if (!hasFiles) {
    ElMessage.warning('选中的项中没有包含任何附件')
    return
  }

  // --- 步骤 2: 执行下载 ---
  totalCount.value = flatFileList.length
  currentCount.value = 0
  downloading.value = true

  try {
    const zipName = `预约附件包_${new Date().toISOString().slice(0, 10)}.zip`

    await downloadFilesAsZip(flatFileList, zipName, (current, total) => {
      currentCount.value = current
    })

    ElMessage.success(`成功打包 ${flatFileList.length} 个文件`)
  } catch (error) {
    ElMessage.error('下载过程中出现异常，请查看控制台')
    console.error(error)
  } finally {
    downloading.value = false
  }
}

const { queryParams, form } = toRefs(data)
// 新增：用于存储已上传成功的文件列表
const uploadedFiles = ref([])
const currentUploadRow = ref([])
const handleSubmitUpload = () => {
  if (uploadedFiles.value.length > 0) {
    if (currentUploadRow.value.relObjectMaterialBizId) {
      try {
        uploadOssFileSubmit({
          relObjectMaterialBizId: currentUploadRow.value.relObjectMaterialBizId,
          fileBizIdList: uploadedFiles.value.map(item => item.fileBizId)
        }).then(response => {
          getFileList()

          editVisible.value = false
        })
      } catch (error) {
        console.log('error', error)

        uploadedFiles.value = []
        proxy.$message.error('文件修改失败')
      }
    } else {
      fileTableList.value.forEach(item => {
        if (item.materialBizId == currentUploadRow.value.materialBizId) {
          item.fileBizIdList = JSON.parse(JSON.stringify(uploadedFiles.value))
          item.status = 'YSC'
        }
      })
    }
  }
  editVisible.value = false
}
// 获取字典数据
const fetchDictData = dictType => {
  let options = []
  try {
    dictStore.dictTypeLists.forEach(item => {
      if (item.dictType == 'sys_no_yes') {
        item.dictItemList.forEach(item2 => {
          item2.value = String(item2.itemValue)
        })
      }
      if (item.dictType == dictType) {
        options = item.dictItemList
      }
    })
    return options
  } catch (error) {
    console.error('获取字典数据失败:', error)
    return []
  }
}
// 重置上传列表（比如关闭弹窗时清空）
const resetUploadedList = () => {
  uploadedFiles.value = []
  if (uploadRef.value) {
    uploadRef.value.clearFiles()
  }
}
const handleUploadFile = row => {
  currentUploadRow.value = JSON.parse(JSON.stringify(row))
  editVisible.value = true
}

const handleDetele = row => {
  proxy.$modal
    .confirm('是否确认删除此行数据？')
    .then(function () {
      if (row.relObjectMaterialBizId) {
        console.log('远程删除')

        return delMaterial(row.relObjectMaterialBizId)
      } else {
        // 本地临时数据，直接从列表中移除
        const index = fileTableList.value.findIndex(
          item => item.materialBizId === row.materialBizId
        )
        if (index !== -1) {
          fileTableList.value.splice(index, 1)
        }
        // 注意：这里不需要 return Promise，因为是同步操作
        // 但为了统一 then 链，可以 return 一个成功标识
        return { code: 200 } // 模拟成功
      }
    })
    .then(res => {
      if (res && res.code == 200) {
        proxy.$modal.msgSuccess('删除成功')
        if (row.relObjectMaterialBizId) {
          getFileList()
        }
      }
    })
    .catch(() => {})
}
const isImageFile = fileName => {
  return /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(fileName || '')
}
const handleUpdate = row => {
  currentUploadRow.value = JSON.parse(JSON.stringify(row))

  if (row.relObjectMaterialBizId) {
    try {
      uploadOssFileList({ objectBizId: row.relObjectMaterialBizId }).then(response => {
        uploadedFiles.value = response.data || []
        editVisible.value = true
      })
    } catch (error) {
      uploadedFiles.value = []
      proxy.$message.error('文件获取失败')
    }
  } else {
    editVisible.value = true
    uploadedFiles.value = JSON.parse(JSON.stringify(row.fileBizIdList))
  }
}
// 下载材料包
const downloadFile = () => {
  let apiMaterialDtoList = []
  let params = {
    projectBizId: userStore.projectInfo.projectBizId || '',
    objectName: '预约附件材料包', //对象名（包名）
    objectBizId: '' //对象业务ID
  }
  if (!props.idsObj.appointmentBizId) {
    if (fileTableList.value.filter(item => item.fileBizIdList.length > 0).length == 0) {
      proxy.$modal.msgError('请先上传文件')
      return
    }
    apiMaterialDtoList = fileTableList.value.map(item => {
      return {
        dataPerson: item.dataPerson, //资料人（字典）
        dataType: item.dataType, //资料类型（字典）
        fileUrlList: item.fileBizIdList.map(item2 => item2.url) //文件url
      }
    })
  } else {
    if (fileTableList.value.filter(item => item.fileUrlList.length > 0).length == 0) {
      proxy.$modal.msgError('请先上传文件')
      return
    }
    apiMaterialDtoList = fileTableList.value.map(item => {
      return {
        dataPerson: item.dataPerson, //资料人（字典）
        dataType: item.dataType, //资料类型（字典）
        fileUrlList: item.fileUrlList
      }
    })
  }
  params.apiMaterialDtoList = apiMaterialDtoList
  try {
    downLoading.value = true
    downloadCompressedFile(params).then(response => {
      downLoading.value = false
      // 创建隐藏的下载链接
      const link = document.createElement('a')
      link.href = response.data.url
      link.target = '_blank' // 新窗口打开

      // 设置下载文件名（重要）
      // 从URL中提取文件名，或者使用返回的文件名
      const fileName = '预约材料包'
      link.download = fileName

      // 触发下载
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    })
  } catch (error) {
    console.log('error', error)

    proxy.$message.error('材料包下载失败')
  } finally {
    downLoading.value = false
  }
}

// 上传前loading加载
function handleBeforeUpload(file) {
  // if (file.name.includes(',')) {
  //   proxy.$modal.msgError('文件名不正确，不能包含英文逗号!')
  //   return false
  // }

  const isLt = file.size / 1024 / 1024 < fileSize.value
  if (!isLt) {
    proxy.$modal.msgError(`上传文件大小不能超过 ${fileSize.value} MB!`)
    return false
  }
  proxy.$modal.loading('正在上传文件，请稍候...')
}
// 文件个数超出
function handleExceed() {
  proxy.$modal.msgError(`一次只能上传${limit.value}个文件!`)
}
// 文件上传成功回调
const uploadSuccess = (res, file, fileList) => {
  console.log('上传成功', res, file)
  proxy.$modal.closeLoading()
  if (res.code === 200) {
    // 构造前端使用的文件对象（保留原始 file 信息 + 后端返回的 url 等）
    const uploadedFile = {
      fileBizId: res.data.fileBizId, // 用于唯一标识
      originalName: res.data.originalName || file.name,
      url: res.data.url,
      size: file.size,
      raw: file.raw // 原始 File 对象（如需后续操作）
    }
    uploadedFiles.value.push(uploadedFile)
    proxy.$message.success('文件上传成功')
  } else {
    proxy.$message.error(res.msg || '上传失败')
  }
}

// 删除已上传的文件（仅从列表移除，不调用后端删除）
const removeUploadedFile = (file, index) => {
  try {
    delUploadFile(file.fileBizId, userStore.projectInfo.projectBizId).then(response => {
      uploadedFiles.value.splice(index, 1)
    })
  } catch (error) {
    proxy.$message.error('文件删除失败')
  }
}
const getFileList = () => {
  loading.value = true
  try {
    if (!props.idsObj.appointmentBizId) {
      uploadMaterialList(queryParams.value).then(response => {
        fileTableList.value = response.data
        if (fileTableList.value.length > 0) {
          fileTableList.value.forEach(item => {
            item.fileBizIdList = []
            item.status = 'WSC'
          })
        }
        loading.value = false
      })
    } else {
      let obj = {
        objectType: 'appointment',
        objectBizId: props.idsObj.appointmentBizId
      }
      uploadRelObjectMaterialList(obj).then(response => {
        fileTableList.value = response.data.records
        loading.value = false
      })
    }
  } catch (error) {
    fileTableList.value = []
  } finally {
    loading.value = false
  }
}
const handleFormValues = () => {
  let submitData = []
  fileTableList.value.forEach(item => {
    submitData.push({
      materialBizId: item.materialBizId,
      fileBizIdList: item.fileBizIdList.map(item => item.fileBizId)
    })
  })
  return submitData
}
// 关闭弹窗时清空已上传列表
watch(editVisible, newVal => {
  if (!newVal) {
    resetUploadedList()
    limit.value = 10
  }
})
const hasLoaded = ref(false) // 新增：是否已加载过数据
watch(
  () => props.activeName,
  newVal => {
    if (newVal === 'accessories') {
      if (!hasLoaded.value) {
        getFileList()
        hasLoaded.value = true
      }
    }
  }
)
// 暴露给父组件
defineExpose({
  handleFormValues
})
</script>
<style lang="scss" scoped>
.fileNameBox {
  width: 70%;
  /* 核心三件套: 强制单行 + 溢出隐藏 + 省略号 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pdf-viewer {
  display: flex;
  flex-direction: column;
  height: 70vh;
}

.pdf-toolbar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid #e4e7ed;
  margin-bottom: 12px;
  .page-info {
    font-size: 14px;
    color: #606266;
  }
}

.pdf-scroll-wrapper {
  flex: 1;
  overflow-y: auto; /* 垂直滚动 */
  border: 1px solid #ebeef5;
  border-radius: 4px;
  background: #f9fafc;
}

.pdf-scroll-container {
  display: flex;
  flex-direction: column;
  align-items: center; /* 页面居中显示 */
  padding: 16px;
}

.pdf-page-canvas {
  display: block;
  max-width: 100%; /* 自适应宽度，防止溢出容器 */
  height: auto;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  margin-bottom: 16px;
}
.pdf-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  color: #409eff;
  gap: 12px;

  .el-icon {
    font-size: 32px;
  }
}
.pdf-viewer {
  display: flex;
  flex-direction: column;
  height: 70vh;
}

.pdf-toolbar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid #e4e7ed;
  margin-bottom: 12px;

  .page-info {
    font-size: 14px;
    color: #606266;
  }
}

.pdf-canvas-wrapper {
  flex: 1;
  overflow: auto;
  text-align: center;
}

.pdf-canvas {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border-radius: 4px;
  margin: 0 auto;
}
.preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
}
.preview-image-wrapper {
  text-align: center;
}
.preview-image {
  max-width: 100%;
  max-height: 70vh;
  object-fit: contain;
}
.preview-pdf {
  width: 100%;
  height: 70vh;
}
.preview-unsupported {
  text-align: center;
  padding: 40px;
}
.preview-unsupported p {
  margin: 16px 0;
  color: #909399;
}
.uploadContainer {
  padding-left: 10px;
  padding-top: 10px;
}
.fileUploadBox {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding: 20px 0;
  border: 1px dashed #dcdfe6;
  height: 200px;
}
.uploadBox {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
  .file {
    font-size: 14px;
    margin-top: 10px;
    color: #409eff;
  }
}
.tip {
  font-size: 14px;
  color: #909399;
  margin: 10px 0 20px 0;
}
.dialogBox {
  width: 100%;
  display: flex;
  justify-content: space-between;
}
.dialogLeft {
  width: 40%;
}
.dialogRight {
  width: 55%;
}
.uploaded-file-item {
  width: 100%;
  background: rgba(247, 248, 250, 1);
  border-radius: 4px;
  padding: 10px;
  margin-bottom: 5px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 16px;
}
</style>
