<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"
              :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">(支持Word,Excel,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="fileName">{{ file.originalName }}</div>
              <el-icon color="red" size="18" @click="removeUploadedFile(file, index)"
                ><Delete
              /></el-icon>
            </div>
          </el-scrollbar>
        </div>
      </div>
    </CommonDialog>
    <el-dialog v-model="imageViewerVisible" title="图片预览" width="60%">
      <div style="text-align: center">
        <el-image :src="imageUrl" fit="contain" />
      </div>
    </el-dialog>
  </div>
</template>

<script setup name="FileUpload">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { downloadFilesAsZip } from '@/utils/zipDownload'; // 引入刚才封装的工具
import CommonDialog from '@/components/commonDialog'
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'
const userStore = useUserStore()
import {
  uploadMaterialList,
  delUploadFile,
  uploadRelObjectMaterialList,
  uploadOssFileList,
  uploadOssFileSubmit,
  downloadCompressedFile,
  delMaterial
} from '@/api/common'
const props = defineProps({
  activeName: { type: String, default: '' }, //tab名称
  idsObj: { type: Object, default: () => ({}) }, //父组件传递过来的id对象
  pageSource: { type: String, default: '' } //页面来源
})
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') // 上传的服务器地址
// 图片查看相关状态
const imageViewerVisible = ref(false)
const imageUrl = ref('')
const downLoading = ref(false)
const data = reactive({
  form: {},
  queryParams: {
    objectType: 'appointment'
  }
})

// 下载材料包
// 状态管理
const downloading = ref(false);
const currentCount = ref(0);
const totalCount = ref(0);

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 handleView = row => {
  imageUrl.value = row.fileUrl
  imageViewerVisible.value = true
}

// 下载材料包
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>
.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>
