<!-- 文件上传下载删除组件 -->
<template>
  <div class="s-upload-file-container">
    <!-- 上传按钮区域 -->
    <div class="upload-btn-wrapper" v-if="!disabled">
      <a-button type="primary" @click="handleOpenUploadModal">
        <Icon icon="ant-design:upload-outlined" />
        选择文件上传
      </a-button>
    </div>

    <!-- 文件列表区域 -->
    <div class="file-list-wrapper">
      <div v-if="displayFileList.length > 0" class="file-list-header">
        <span class="file-count">共 {{ displayFileList.length }} 个文件</span>
        <a-button
          type="link"
          size="small"
          :loading="downloadingAll"
          @click="handleDownloadAll"
        >
          <Icon icon="ant-design:download-outlined" />
          下载全部
        </a-button>
      </div>
      <a-spin :spinning="loading">
        <a-empty v-if="!loading && displayFileList.length === 0" description="暂无文件" />
        <div v-else class="file-list">
          <div
            v-for="file in displayFileList"
            :key="file.fileId || file.id"
            class="file-item"
          >
            <!-- 文件信息 -->
            <div class="file-info">
              <Icon icon="ant-design:file-outlined" class="file-icon" />
              <span class="file-name">{{ file.fileName }}</span>
              <a-tag :color="getSecretLevelColor(file.secretLevel)" class="secret-tag">
                {{ getSecretLevelLabel(file.secretLevel) }}
              </a-tag>
              <a-tag v-if="file.pending" color="orange" class="secret-tag">
                待保存
              </a-tag>
              <span v-if="file.fileSize" class="file-size">{{ formatFileSize(file.fileSize) }}</span>
            </div>

            <!-- 操作按钮 -->
            <div class="file-actions">
              <a-button
                type="link"
                size="small"
                @click="handleDownload(file)"
              >
                <Icon icon="ant-design:download-outlined" />
                下载
              </a-button>
              <a-button
                v-if="!disabled"
                type="link"
                size="small"
                danger
                @click="handleDelete(file)"
              >
                <Icon icon="ant-design:delete-outlined" />
                删除
              </a-button>
            </div>
          </div>
        </div>
      </a-spin>
    </div>

    <!-- 上传弹窗 -->
    <SFileUploadModal
      v-model:visible="uploadModalVisible"
      :secret-level-options="secretLevelOptions"
      :business-id="bussinessId"
      :multiple="multiple"
      @upload-success="handleUploadSuccess"
      @upload-error="handleUploadError"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { Icon } from '/src/components/Icon';
import { defHttp } from '/src/utils/http/axios';
import { useMessage } from '/src/hooks/web/useMessage';
import SFileUploadModal from './SFileUploadModal.vue';

const { createMessage, createConfirm } = useMessage();

const props = defineProps({
  bussinessId: {
    type: String,
    default: ''
  },
  bussinessSecretLevel: {
    type: Number,
    default: 1,
    validator: (value: number) => [1, 2, 3, 4].includes(value)
  },
  disabled: {
    type: Boolean,
    default: false
  },
  multiple: {
    type: Boolean,
    default: true
  }
});

const emit = defineEmits(['upload-success', 'delete-success', 'upload-error']);

const serverFileList = ref<any[]>([]);
const pendingFileList = ref<any[]>([]);
const loading = ref<boolean>(false);
const uploadModalVisible = ref<boolean>(false);
const binding = ref<boolean>(false);
const downloadingAll = ref<boolean>(false);

const displayFileList = computed(() => {
  return [
    ...serverFileList.value.map(f => ({ ...f, pending: false })),
    ...pendingFileList.value.map(f => ({ ...f, pending: true }))
  ];
});

const SECRET_LEVEL_CONFIG = {
  1: { label: '非密', color: 'success' },
  2: { label: '内部', color: 'processing' },
  3: { label: '秘密', color: 'warning' },
  4: { label: '机密', color: 'error' }
};

function getSecretLevelInfo(level: number) {
  return SECRET_LEVEL_CONFIG[level] || SECRET_LEVEL_CONFIG[1];
}

function getSecretLevelLabel(level: number) {
  return getSecretLevelInfo(level).label;
}

function getSecretLevelColor(level: number) {
  return getSecretLevelInfo(level).color;
}

function formatFileSize(bytes: number): string {
  if (!bytes || bytes === 0) return '';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
}

const secretLevelOptions = computed(() => {
  const level = props.bussinessSecretLevel;
  const options = [];
  options.push({ label: '非密', value: 1 });
  if (level >= 2) options.push({ label: '内部', value: 2 });
  if (level >= 3) options.push({ label: '秘密', value: 3 });
  if (level >= 4) options.push({ label: '机密', value: 4 });
  return options;
});

function handleOpenUploadModal() {
  uploadModalVisible.value = true;
}

async function handleUploadSuccess(result: any) {
  if (result.results && Array.isArray(result.results)) {
    result.results.forEach((fileInfo: any) => {
      if (!fileInfo.bound) {
        pendingFileList.value.push({
          fileId: fileInfo.fileId,
          fileName: fileInfo.fileName,
          filePath: fileInfo.filePath,
          fileSize: fileInfo.fileSize,
          secretLevel: fileInfo.secretLevel,
          fileUploadType: fileInfo.fileUploadType
        });
      }
    });
  }
  if (props.bussinessId) {
    await loadFileList();
  }
  emit('upload-success', result);
}

function handleUploadError(error: any) {
  emit('upload-error', error);
}

async function handleDownload(file: any) {
  try {
    const fileUrl = file.filePath;
    const fileName = file.fileName || fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
    const domainUrl = import.meta.env.VITE_GLOB_DOMAIN_URL;
    const data = await defHttp.get(
      { url: `${domainUrl}/sys/file/download`, params: { fileUrl }, responseType: 'blob' },
      { isTransformResponse: false }
    );
    if (!data || data.size === 0) {
      createMessage.warning('文件下载失败');
      return;
    }
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
      window.navigator.msSaveBlob(new Blob([data]), fileName);
    } else {
      const blobUrl = window.URL.createObjectURL(new Blob([data]));
      const link = document.createElement('a');
      link.style.display = 'none';
      link.href = blobUrl;
      link.setAttribute('download', fileName);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(blobUrl);
    }
  } catch (error) {
    console.error('下载失败:', error);
    createMessage.error('文件下载失败');
  }
}

async function handleDownloadAll() {
  const files = displayFileList.value;
  if (files.length === 0) return;

  downloadingAll.value = true;
  let successCount = 0;
  let failCount = 0;

  for (const file of files) {
    try {
      await handleDownload(file);
      successCount++;
    } catch (error) {
      failCount++;
      console.error(`下载文件"${file.fileName}"失败:`, error);
    }
  }

  downloadingAll.value = false;

  if (successCount > 0) {
    createMessage.success(`成功下载 ${successCount} 个文件${failCount > 0 ? `，${failCount} 个失败` : ''}`);
  } else {
    createMessage.error('所有文件下载失败');
  }
}

function handleDelete(file: any) {
  createConfirm({
    iconType: 'warning',
    title: '确认删除',
    content: `确定要删除文件"${file.fileName}"吗？`,
    okText: '确认',
    cancelText: '取消',
    onOk: async () => {
      try {
        loading.value = true;
        await defHttp.get({
          url: '/sys/file/delete',
          params: { id: file.fileId || file.id }
        });
        createMessage.success('文件删除成功');
        if (file.pending) {
          pendingFileList.value = pendingFileList.value.filter(f => f.fileId !== file.fileId);
        } else {
          serverFileList.value = serverFileList.value.filter(f => (f.id || f.fileId) !== (file.id || file.fileId));
        }
        emit('delete-success', file.fileId || file.id);
      } catch (error) {
        console.error('删除失败:', error);
        createMessage.error('文件删除失败');
      } finally {
        loading.value = false;
      }
    }
  });
}

async function loadFileList() {
  if (!props.bussinessId) {
    return;
  }

  try {
    loading.value = true;
    const result = await defHttp.get({
      url: '/sys/file/getFileInfoByBussinessId',
      params: { bussinessId: props.bussinessId }
    });

    if (Array.isArray(result)) {
      serverFileList.value = result;
    } else {
      serverFileList.value = [];
    }
  } catch (error) {
    console.error('加载文件列表失败:', error);
    serverFileList.value = [];
    createMessage.error('加载文件列表失败');
  } finally {
    loading.value = false;
  }
}

//这个是在表单id还没有生成之前上传了附件，附件表没有存储bussinessId。当业务表保存后有id了，再把bussinessId更新到这些附件上去
async function bindBussinessId(newBussinessId: string) {
  if (!newBussinessId) {
    createMessage.warning('bussinessId 不能为空');
    return false;
  }

  if (pendingFileList.value.length === 0) {
    return true;
  }

  const fileIds = pendingFileList.value.map(f => f.fileId).join(',');

  try {
    binding.value = true;
    await defHttp.get({
      url: '/sys/file/updateFilesInfo',
      params: {
        bussinessId: newBussinessId,
        fileIds: fileIds
      }
    });
    createMessage.success(`成功关联 ${pendingFileList.value.length} 个文件`);
    pendingFileList.value = [];
    await loadFileList();
    return true;
  } catch (error) {
    console.error('关联文件失败:', error);
    createMessage.error('关联文件失败，请重试');
    return false;
  } finally {
    binding.value = false;
  }
}

function getPendingFileIds(): string[] {
  return pendingFileList.value.map(f => f.fileId);
}

function hasPendingFiles(): boolean {
  return pendingFileList.value.length > 0;
}

defineExpose({
  bindBussinessId,
  getPendingFileIds,
  hasPendingFiles,
  loadFileList
});

watch(() => props.bussinessId, (newVal) => {
  if (newVal && newVal.length > 0) {
    loadFileList();
  } else {
    serverFileList.value = [];
  }
}, { immediate: true });
</script>

<style lang="less" scoped>
.s-upload-file-container {
  width: 100%;
  max-width: 100%;

  .upload-btn-wrapper {
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .file-list-wrapper {
    width: 100%;
    min-height: 100px;
    padding: 12px;
    background: #fafafa;
    border-radius: 4px;

    .file-list-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;
      padding-bottom: 8px;
      border-bottom: 1px solid #f0f0f0;

      .file-count {
        font-size: 13px;
        color: #8c8c8c;
      }
    }
  }

  .file-list {
    .file-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px;
      background: #fff;
      border: 1px solid #f0f0f0;
      border-radius: 4px;
      margin-bottom: 8px;
      transition: all 0.3s;

      &:hover {
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      }

      &:last-child {
        margin-bottom: 0;
      }

      .file-info {
        display: flex;
        align-items: center;
        gap: 8px;
        flex: 1;
        overflow: hidden;

        .file-icon {
          font-size: 16px;
          color: #1890ff;
          flex-shrink: 0;
        }

        .file-name {
          font-size: 14px;
          color: #262626;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

        .secret-tag {
          margin-left: 4px;
          font-weight: 500;
          flex-shrink: 0;
        }

        .file-size {
          font-size: 12px;
          color: #8c8c8c;
          flex-shrink: 0;
        }
      }

      .file-actions {
        display: flex;
        gap: 8px;
        flex-shrink: 0;
      }
    }
  }
}
</style>
