<template>
  <div>
    <a-upload :action="currentUploadUrl" :file-list="fileList" :accept="accept" :multiple="multiple"
      :disabled="isLoading || see" :show-upload-list="false" :before-upload="beforeUpload" @preview="previewFile"
      @remove="deleteFile" v-bind="$attrs">
      <a-button :loading="isLoading" :disabled="see" ref="uploadButton" v-show="false">
      </a-button>
    </a-upload>
    <a-button :loading="isLoading" :disabled="see" type="primary" v-if="closeButton"
      @click="$refs.uploadButton.$el.click()" v-bind="$attrs">
      <paas-icon v-if="icon" :icon="icon" />
      <span v-if="label">{{ label }}</span>
    </a-button>
    <!-- 文件统计信息 -->
    <div v-if="datas.length > 0 && showHis" :style="fileStatsStyle">
      共 {{ datas.length }} 个文件
      <span v-if="paginatedDatas.length < datas.length">
        ，当前显示 {{ paginatedDatas.length }} 个
      </span>
    </div>

    <!-- 使用卡片式布局展示已上传的文件 -->
    <div v-if="datas.length > 0 && showHis" :style="fileListContainerStyle">
      <div v-for="(file, index) in paginatedDatas" :key="file.newName || index" :style="fileCardStyle"
        @mouseenter="$event.currentTarget.style.borderColor = '#40a9ff'; $event.currentTarget.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.15)'; $event.currentTarget.style.backgroundColor = '#fff'"
        @mouseleave="$event.currentTarget.style.borderColor = '#d9d9d9'; $event.currentTarget.style.boxShadow = 'none'; $event.currentTarget.style.backgroundColor = '#fafafa'">
        <div :style="fileIconStyle">
          <FileOutlined v-if="!isImage(file.originalName)" />
          <PictureOutlined v-else />
        </div>
        <div :style="fileInfoStyle">
          <div :style="fileNameStyle" :title="file.originalName">{{ file.originalName }}</div>
          <div :style="fileSizeStyle" v-if="file.size">{{ formatFileSize(file.size) }}</div>
        </div>
        <div :style="fileActionsStyle">
          <a-tooltip title="查看">
            <EyeOutlined @click="previewFile(file)" :style="actionIconStyle" @mouseenter="$event.currentTarget.style.color = '#1890ff'" @mouseleave="$event.currentTarget.style.color = '#595959'" />
          </a-tooltip>
          <a-tooltip title="下载">
            <DownloadOutlined @click="download(file)" v-show="!see" :style="actionIconStyle" @mouseenter="$event.currentTarget.style.color = '#1890ff'" @mouseleave="$event.currentTarget.style.color = '#595959'" />
          </a-tooltip>
          <a-tooltip title="删除">
            <DeleteOutlined @click="deleteFile(file)" v-show="!see" :style="actionIconStyle" @mouseenter="$event.currentTarget.style.color = '#ff4d4f'" @mouseleave="$event.currentTarget.style.color = '#595959'" />
          </a-tooltip>
        </div>
      </div>
    </div>

    <!-- 分页控件 -->
    <div v-if="datas.length > pageSize && showHis" :style="paginationContainerStyle">
      <a-pagination v-model:current="currentPage" :page-size="pageSize" :total="datas.length" size="small"
        show-less-items />
    </div>

    <!-- 图片预览模态框 -->
    <a-modal v-model:open="previewVisible" :title="previewTitle" :footer="null" @cancel="previewVisible = false">
      <img alt="预览图片" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script>
import {
  DeleteOutlined,
  DownloadOutlined,
  EyeOutlined,
  FileOutlined,
  PictureOutlined
} from '@ant-design/icons-vue';
import { message, Modal } from 'ant-design-vue';

export default {
  name: 'PaasUpload',
  components: {
    FileOutlined,
    PictureOutlined,
    EyeOutlined,
    DownloadOutlined,
    DeleteOutlined
  },
  inheritAttrs: false, // 禁用自动继承，手动控制透传
  expose: ['openUpload'], // 暴露openUpload方法供外部调用
  inject: {
    labelWidth: {
      from: 'labelWidth',
      default: '90px'
    },
    defaultColSpan: {
      from: 'defaultColSpan',
      default: 12
    }
  },
  props: {
    closeButton: {
      type: Boolean,
      default: false,
    },
    icon: {
      type: String,
      default: "",
    },
    placeholder: {
      type: String,
      default: "",
    },
    textWidth: {
      type: String,
      default: ""
    },
    modelValue: {
      type: [String, Object, Array],
      default: '',
    },
    colSpan: { type: Number }, // 自定义列跨度
    accept: {
      type: String,
      default: "",
    },
    showHis: {
      type: Boolean,
      default: true,
    },
    uploadUrl: {
      type: String,
      default: '/system/secure/minio/uploadFile',
    },
    openUploadUrl: {
      type: String,
      default: '/system/open/minio/uploadFile',
    },
    isOpen: {
      type: Boolean,
      default: false,
    },
    showUrl: {
      type: String,
      default: '/system/secure/minio/preview',
    },
    openShowUrl: {
      type: String,
      default: '/system/open/minio/preview',
    },
    downloadUrl: {
      type: String,
      default: '/system/secure/minio/getUrl',
    },
    openDownloadUrl: {
      type: String,
      default: '/system/open/minio/getUrl',
    },
    deleteUrl: {
      type: String,
      default: '/system/secure/minio/delete',
    },
    openDeleteUrl: {
      type: String,
      default: '/system/open/minio/delete',
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    name: {
      type: String,
      default: 'file',
    },
    params: {
      type: Object,
      default: () => ({})
    },
    success: {
      type: Function,
      default: (data) => { }
    },
    label: {
      type: String,
      default: ''
    },
    rules: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      datas: [],
      fileList: [],
      isLoading: false,
      currentPage: 1,
      pageSize: 10,
      previewVisible: false,
      previewImage: '',
      previewTitle: '',
      isUploading: false,
      windowWidth: window.innerWidth
    };
  },
  computed: {
    see() {
      return this.$store.forms.see;
    },
    paginatedDatas() {
      const startIndex = (this.currentPage - 1) * this.pageSize;
      const endIndex = startIndex + this.pageSize;
      return this.datas.slice(startIndex, endIndex);
    },
    currentUploadUrl() {
      let baseUrl = this.isOpen ? this.openUploadUrl : this.uploadUrl;
      if (this.multiple) {
        if (!baseUrl.endsWith('s')) {
          if (baseUrl.includes('.')) {
            const lastDotIndex = baseUrl.lastIndexOf('.');
            baseUrl = baseUrl.substring(0, lastDotIndex) + 's' + baseUrl.substring(lastDotIndex);
          } else {
            baseUrl = baseUrl + 's';
          }
        }
      }
      return baseUrl;
    },
    currentShowUrl() {
      return this.isOpen ? this.openShowUrl : this.showUrl;
    },
    currentDownloadUrl() {
      return this.isOpen ? this.openDownloadUrl : this.downloadUrl;
    },
    currentDeleteUrl() {
      return this.isOpen ? this.openDeleteUrl : this.deleteUrl;
    },
    isMobile() {
      return this.windowWidth <= 768;
    },
    fileListContainerStyle() {
      return {
        marginTop: '8px',
        maxWidth: '100%'
      };
    },
    fileCardStyle() {
      const baseStyle = {
        display: 'flex',
        alignItems: 'center',
        padding: this.isMobile ? '8px' : '8px 12px',
        border: '1px solid #d9d9d9',
        borderRadius: '6px',
        marginBottom: '8px',
        transition: 'all 0.3s',
        backgroundColor: '#fafafa',
        boxSizing: 'border-box',
        flexWrap: 'nowrap'
      };
      return baseStyle;
    },
    fileIconStyle() {
      return {
        fontSize: '24px',
        color: '#1890ff',
        marginRight: '12px',
        flexShrink: 0,
        width: '24px',
        height: '24px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center'
      };
    },
    fileInfoStyle() {
      return {
        flex: 1,
        minWidth: 0,
        paddingRight: '8px'
      };
    },
    fileNameStyle() {
      return {
        fontSize: this.isMobile ? '13px' : '14px',
        color: '#262626',
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        whiteSpace: 'nowrap',
        marginBottom: '2px'
      };
    },
    fileSizeStyle() {
      return {
        fontSize: '12px',
        color: '#8c8c8c',
        marginTop: '0'
      };
    },
    fileActionsStyle() {
      return {
        display: 'flex',
        gap: this.isMobile ? '8px' : '12px',
        flexShrink: 0,
        alignItems: 'center'
      };
    },
    actionIconStyle() {
      return {
        fontSize: this.isMobile ? '14px' : '16px',
        color: '#595959',
        cursor: 'pointer',
        transition: 'color 0.3s',
        padding: this.isMobile ? '2px' : '4px'
      };
    },
    fileStatsStyle() {
      return {
        marginTop: '8px',
        fontSize: '12px',
        color: '#8c8c8c'
      };
    },
    paginationContainerStyle() {
      return {
        marginTop: '12px',
        display: 'flex',
        justifyContent: 'flex-end'
      };
    }
  },
  watch: {
    modelValue: {
      handler(newValue) {
        this.pushFile(newValue);
      },
      immediate: true
    },
    datas: {
      handler() {
        this.currentPage = 1;
      },
      deep: true
    }
  },
  mounted() {
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    handleResize() {
      this.windowWidth = window.innerWidth;
    },
    openUpload() {
      this.$refs.uploadButton.$el.click();
    },
    pushFile(newValue) {
      if (!newValue) {
        this.datas = [];
        return;
      }

      let parsed;
      try {
        // 如果是字符串且不是有效的JSON，直接返回
        if (typeof newValue === 'string' && newValue.trim() === '') {
          this.datas = [];
          return;
        }

        parsed = typeof newValue === 'string' ? JSON.parse(newValue) : newValue;
      } catch (e) {
        console.error('解析文件数据出错:', e);
        this.datas = [];
        return;
      }

      if (Array.isArray(parsed)) {
        this.datas = [...parsed];
      } else if (parsed && typeof parsed === 'object') {
        this.datas = [parsed];
      } else {
        this.datas = [];
      }
    },
    // 使用全局上传方法
    customRequest() {
      // 防止重复上传
      if (this.isUploading || this.fileList.length === 0) {
        return;
      }

      this.isUploading = true;
      this.isLoading = true;

      const formData = new FormData();
      if (this.multiple) {
        this.fileList.forEach((file) => {
          formData.append("files", file);
        });
      } else {
        formData.append("file", this.fileList[0]);
      }
      Object.keys(this.params).forEach((key) => {
        formData.append(key, this.params[key]);
      });

      // 调用全局的 $upload 方法
      this.$upload(this.currentUploadUrl, formData)
        .then((res) => {
          this.isLoading = false;
          this.isUploading = false;
          if (res.data.code == this.$success) {
            this.fileList = []; // 清空文件列表
            message.success(res.data.msg);

            // 更新数据
            if (this.multiple) {
              // 多文件上传，合并到现有数据中
              const newFiles = Array.isArray(res.data.data) ? res.data.data : [res.data.data];
              this.datas = [...this.datas, ...newFiles];
            } else {
              // 单文件上传，替换现有数据
              this.datas = Array.isArray(res.data.data) ? res.data.data : [res.data.data];
            }

            // 触发更新
            this.$emit('update:modelValue', JSON.stringify(this.datas));
            this.success(res.data.data);
          } else {
            message.error(res.data.msg || "文件上传失败！");
          }
        })
        .catch((e) => {
          this.isLoading = false;
          this.isUploading = false;
          this.fileList = []; // 出错时也清空文件列表
          message.error("文件上传失败！");
          console.error(e);
        });
    },
    // 选择文件之前
    beforeUpload(file) {
      if (!this.multiple && this.datas.length > 0) {
        message.warn("当前信息只支持上传一个附件，请删除后重新上传！");
        return false;
      }

      // 重置状态
      this.fileList = [];
      this.isUploading = false;

      this.fileList.push(file);
      this.customRequest();
      return false; // 阻止自动上传
    },
    previewFile(file) {
      // 确保传递正确的参数
      const params = {
        filename: file.newName,
        originalName: file.originalName
      };

      this.$get(this.currentShowUrl, params)
        .then((res) => {
          // 检查返回的数据是否是图片URL
          if (res.data && (res.data.startsWith('http') || res.data.startsWith('/'))) {
            // 如果返回的是URL，则判断是否为图片
            if (this.isImage(file.originalName)) {
              // 使用专用的图片预览模态框
              this.previewImage = res.data;
              this.previewTitle = file.originalName;
              this.previewVisible = true;
            } else if (file.originalName.endsWith('.pdf') && res.data.includes('.pdf')) {
              window.open(res.data, '_blank');
            } else {
              // 对于非图片和PDF文件，尝试在新窗口打开
              window.open(res.data, '_blank');
            }
          } else {
            // 如果返回的不是URL，而是Base64数据或其他格式
            if (this.isImage(file.originalName)) {
              // 使用专用的图片预览模态框
              this.previewImage = res.data;
              this.previewTitle = file.originalName;
              this.previewVisible = true;
            } else {
              message.warning('不支持该类型文件查看');
            }
          }
        })
        .catch((e) => {
          message.error('预览文件失败');
          console.error(e);
        });
    },
    download(file) {
      Modal.confirm({
        content: '确定下载？',
        onOk: () => {
          // 确保传递正确的参数
          const params = {
            filename: file.newName,
            originalName: file.originalName
          };

          this.$get(this.currentDownloadUrl, params)
            .then(res => {
              if (res.data) {
                const link = document.createElement('a');
                link.href = res.data;
                link.download = file.originalName;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
              } else {
                message.error('获取下载链接失败');
              }
            })
            .catch((e) => {
              message.error('下载失败');
              console.error(e);
            });
        },
      });
    },
    deleteFile(file) {
      Modal.confirm({
        content: '确定删除？',
        onOk: () => {
          this.$postForm(this.currentDeleteUrl, { filename: file.newName })
            .then((res) => {
              if (res.data.code === 200) {
                this.datas = this.datas.filter((item) => item.newName !== file.newName);
                // 修复：当没有文件时返回空字符串而不是空数组的JSON字符串
                const valueToSend = this.datas.length > 0 ? JSON.stringify(this.datas) : '';
                this.$emit('update:modelValue', valueToSend);
                message.success('删除成功');
              } else {
                message.error(res.data.msg);
              }
            })
            .catch((e) => {
              message.error('删除失败');
              console.error(e);
            });
        },
      });
    },
    isImage(filename) {
      const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.tiff'];
      return imageExtensions.some((ext) => filename.toLowerCase().includes(ext));
    },
    // 提供给表单使用的验证方法
    validate() {
      // 如果有验证规则，执行验证
      if (this.rules && this.rules.length > 0) {
        // 检查是否有必填规则且没有文件
        const requiredRule = this.rules.find(rule => rule.required);
        if (requiredRule && this.datas.length === 0) {
          return Promise.reject(requiredRule.message || '请上传文件');
        }
      }
      return Promise.resolve();
    },
    // 清空文件
    clear() {
      this.datas = [];
      this.fileList = [];
      this.isUploading = false;
      this.$emit('update:modelValue', '');
    },
    // 格式化文件大小
    formatFileSize(size) {
      if (size < 1024) {
        return size + ' B';
      } else if (size < 1024 * 1024) {
        return (size / 1024).toFixed(1) + ' KB';
      } else if (size < 1024 * 1024 * 1024) {
        return (size / (1024 * 1024)).toFixed(1) + ' MB';
      } else {
        return (size / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
      }
    }
  },
};
</script>