<template>
  <div class="sa-upload-image">
    <div class="upload-container sa-flex sa-flex-wrap">
      <!-- 已上传的图片列表 -->
      <sa-draggable v-if="imageList.length > 0" v-model="imageList" :animation="300" handle=".sortable-drag"
        item-key="url" @end="handleSort" class="sa-flex sa-flex-wrap">
        <template #item="{ element, index }">
          <div class="image-item mr-2px" :class="{ 'compact-mode': compact }"
            :style="{ width: size + 'px', height: size + 'px' }">
            <el-image :src="element" fit="cover" :preview-src-list="compact ? [] : imageList"
              :initial-index="compact ? 0 : index" :preview-teleported="true"
              @click="compact ? previewImage(element, index) : null"
              :style="{ cursor: compact ? 'pointer' : 'default' }">
              <template #error>
                <div class="image-error">
                  <el-icon>
                    <Picture />
                  </el-icon>
                </div>
              </template>
            </el-image>
            <div class="image-mask" :class="{ 'compact-mask': compact }">
              <template v-if="compact">
                <el-icon @click.stop="removeImage(index)" :title="t('common.delete')" size="12">
                  <Delete />
                </el-icon>
              </template>
              <template v-else>
                <el-icon class="sortable-drag" :title="t('common.dragSort')" size="24">
                  <Rank />
                </el-icon>
                <el-icon @click="previewImage(element, index)" :title="t('common.preview')" size="24">
                  <ZoomIn />
                </el-icon>
                <el-icon @click="removeImage(index)" :title="t('common.delete')" size="24">
                  <Delete />
                </el-icon>
              </template>
            </div>
          </div>
        </template>
      </sa-draggable>

      <!-- 上传按钮 -->
      <div v-if="!maxCount || imageList.length < maxCount" class="upload-wrapper"
        :style="{ width: size + 'px', height: size + 'px' }">
        <div class="upload-trigger" :class="{ 'compact-trigger': compact, 'is-uploading': uploading }"
          :style="{ width: size + 'px', height: size + 'px' }" @click="handleUploadClick">
          <el-icon class="upload-icon" :size="compact ? 16 : 24">
            <Plus />
          </el-icon>
          <div v-if="!compact" class="upload-text">{{
            placeholder || t('common.uploadImage')
          }}</div>
        </div>

        <!-- 自定义loading遮罩 -->
        <div v-if="uploading" class="upload-loading">
          <div class="loading-spinner"></div>
          <div v-if="!compact" class="loading-text">{{ t('common.uploading') }}</div>
        </div>
      </div>

      <!-- 隐藏的文件输入框 -->
      <input ref="fileInputRef" type="file" :accept="acceptString" :multiple="multiple" style="display: none"
        @change="handleFileSelect" />
    </div>

    <!-- 提示信息 -->
    <div v-if="showTip" class="upload-tip">
      <span v-if="maxCount">{{ t('common.maxUpload', { count: maxCount }) }}，</span>
      <span v-if="accept && accept.length">{{ t('common.supportFormats', { formats: accept.join('、') }) }}，</span>
      <span v-if="maxSize">{{ t('common.maxFileSize', { size: maxSize }) }}</span>
    </div>

    <!-- 图片预览弹窗 -->
    <el-image-viewer v-if="previewVisible" :url-list="previewImageList" :initial-index="previewInitialIndex"
      :infinite="false" :hide-on-click-modal="true" :teleported="true" :z-index="3000" @close="closePreview" />
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue';
import { ElMessage, ElImageViewer } from 'element-plus';
import { Picture, Plus, Rank, ZoomIn, Delete } from '@element-plus/icons-vue';
import SaDraggable from 'vuedraggable';
import adminApi from '@/app/admin/api';

export default {
  name: 'SaUploadImage',
  components: {
    Picture,
    Plus,
    Rank,
    ZoomIn,
    Delete,
    SaDraggable,
    ElImageViewer,
  },
};
</script>

<script setup>
import { useI18n } from 'vue-i18n';

const { t } = useI18n();

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => [],
  },
  // 是否直传，默认为true
  directUpload: {
    type: Boolean,
    default: true,
  },
  // 最大上传数量
  maxCount: {
    type: Number,
    default: 0,
  },
  // 支持的文件格式
  accept: {
    type: Array,
    default: () => ['jpg', 'jpeg', 'png'],
  },
  // 最大文件大小(MB)
  maxSize: {
    type: Number,
    default: 2,
  },
  // 是否支持多选
  multiple: {
    type: Boolean,
    default: true,
  },
  // 图片尺寸
  size: {
    type: Number,
    default: 100,
  },
  // 占位符文本
  placeholder: {
    type: String,
    default: '',
  },
  // 是否显示提示信息
  showTip: {
    type: Boolean,
    default: true,
  },
  // 精简模式
  compact: {
    type: Boolean,
    default: false,
  },
  // 图片宽高比例要求 (宽/高)
  aspectRatio: {
    type: Number,
    default: null,
  },
  // 是否强制执行宽高比例
  enforceAspectRatio: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(['update:modelValue', 'change']);

// 文件输入框引用
const fileInputRef = ref();

// 图片列表
const imageList = ref([...props.modelValue]);

// 上传loading状态
const uploading = ref(false);

// 计算接受的文件类型字符串
const acceptString = computed(() => {
  return props.accept.map((type) => `.${type}`).join(',');
});

// 添加一个标志来防止循环更新
let isUpdatingFromProps = false;
let isUpdatingFromInternal = false;

// 数组比较函数
const arraysEqual = (a, b) => {
  if (a.length !== b.length) return false;
  return a.every((val, index) => val === b[index]);
};

// 监听外部数据变化
watch(
  () => props.modelValue,
  (newValue) => {
    if (isUpdatingFromInternal) return;

    const currentValue = imageList.value;
    if (!arraysEqual(newValue, currentValue)) {
      isUpdatingFromProps = true;
      imageList.value = [...newValue];
      setTimeout(() => {
        isUpdatingFromProps = false;
      }, 0);
    }
  },
  { deep: true },
);

// 监听内部数据变化
watch(
  imageList,
  (newValue) => {
    if (isUpdatingFromProps) return;

    if (!arraysEqual(newValue, props.modelValue)) {
      isUpdatingFromInternal = true;
      emit('update:modelValue', [...newValue]);
      emit('change', [...newValue]);
      setTimeout(() => {
        isUpdatingFromInternal = false;
      }, 0);
    }
  },
  { deep: true },
);

// 处理上传点击
const handleUpload = () => {
  if (props.directUpload) {
    // 直传模式，直接打开文件选择
    fileInputRef.value?.click();
  } else {
    // 非直传模式，打开文件管理弹窗
    openFileManager();
  }
};

// 处理点击事件（带上传状态检查）
const handleUploadClick = () => {
  if (!uploading.value) {
    handleUpload();
  }
};

// 处理文件选择
const handleFileSelect = async (event) => {
  const files = Array.from(event.target.files);

  if (!files.length) return;

  // 检查数量限制
  if (props.maxCount && imageList.value.length + files.length > props.maxCount) {
    ElMessage.warning(t('message.maxUploadLimit', { count: props.maxCount }));
    return;
  }

  // 验证文件
  const validFiles = [];
  for (const file of files) {
    if (await validateFile(file)) {
      validFiles.push(file);
    }
  }

  if (validFiles.length === 0) return;

  // 开始上传，显示loading
  uploading.value = true;

  // 上传文件
  try {
    const uploadPromises = validFiles.map((file) => uploadFile(file));
    const results = await Promise.all(uploadPromises);

    // 添加成功上传的图片
    results.forEach((result) => {
      if (result.success) {
        imageList.value.push(result.url);
      }
    });

    const successCount = results.filter((r) => r.success).length;
    if (successCount > 0) {
      ElMessage.success(t('message.uploadSuccess', { count: successCount }));
    }

    // 如果有失败的，显示失败信息
    const failedCount = results.length - successCount;
    if (failedCount > 0) {
      ElMessage.error(t('message.uploadFailed', { count: failedCount }));
    }
  } catch (error) {
    ElMessage.error(t('message.uploadError') + ': ' + error.message);
  } finally {
    // 无论成功还是失败，都关闭loading
    uploading.value = false;
  }

  // 清空文件输入框
  event.target.value = '';
};

// 验证文件
const validateFile = async (file) => {
  // 检查文件类型
  const fileExtension = file.name.split('.').pop().toLowerCase();
  if (!props.accept.includes(fileExtension)) {
    ElMessage.warning(
      t('message.unsupportedFormat', {
        extension: fileExtension,
        formats: props.accept.join('、'),
      }),
    );
    return false;
  }

  // 检查文件大小
  const fileSizeMB = file.size / 1024 / 1024;
  if (props.maxSize && fileSizeMB > props.maxSize) {
    ElMessage.warning(t('message.fileSizeExceeded', { size: props.maxSize }));
    return false;
  }

  // 检查图片宽高比例
  if (props.aspectRatio && props.enforceAspectRatio) {
    const isValidRatio = await validateImageAspectRatio(file, props.aspectRatio);
    if (!isValidRatio) {
      const ratioText = props.aspectRatio === 1 ? '1:1' : `${props.aspectRatio}:1`;
      ElMessage.warning(t('message.invalidAspectRatio', { ratio: ratioText }));
      return false;
    }
  }

  return true;
};

// 验证图片宽高比例
const validateImageAspectRatio = (file, expectedRatio) => {
  return new Promise((resolve) => {
    const img = new Image();
    const url = URL.createObjectURL(file);

    img.onload = () => {
      const actualRatio = img.width / img.height;
      const tolerance = 0.1; // 允许10%的误差
      const isValid = Math.abs(actualRatio - expectedRatio) <= tolerance;
      URL.revokeObjectURL(url);
      resolve(isValid);
    };

    img.onerror = () => {
      URL.revokeObjectURL(url);
      resolve(false);
    };

    img.src = url;
  });
};

// 上传文件
const uploadFile = async (file) => {
  try {
    var formData = new FormData();
    formData.append('file', file);
    const response = await adminApi.file.upload({}, formData);
    if (response.code == '200') {
      return {
        success: true,
        url: response.data,
      };
    } else {
      throw new Error(response.msg || t('message.uploadFailed'));
    }
  } catch (error) {
    console.error('上传文件失败:', error);
    return {
      success: false,
      error: error.message,
    };
  }
};

// 打开文件管理器（非直传模式）
const openFileManager = () => {
  // 这里可以集成现有的文件管理器组件
  console.log('打开文件管理器');
  ElMessage.info('文件管理器功能待实现');
};

// 图片预览状态
const previewVisible = ref(false);
const previewImageUrl = ref('');
const previewImageList = ref([]);
const previewInitialIndex = ref(0);

// 预览图片
const previewImage = (url, index = 0) => {
  previewImageUrl.value = url;
  previewImageList.value = [...imageList.value];
  previewInitialIndex.value = index;
  previewVisible.value = true;
};

// 关闭预览
const closePreview = () => {
  previewVisible.value = false;
  previewImageUrl.value = '';
  previewImageList.value = [];
  previewInitialIndex.value = 0;
};

// 删除图片
const removeImage = (index) => {
  imageList.value.splice(index, 1);
};

// 处理拖拽排序
const handleSort = () => {
  // 拖拽排序后自动触发 watch 更新
  console.log('图片排序已更新');
};
</script>

<style lang="scss" scoped>
.sa-upload-image {
  .upload-container {
    gap: 8px;
  }

  .image-item {
    position: relative;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid #dcdfe6;

    .el-image {
      width: 100%;
      height: 100%;
    }

    .image-error {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 100%;
      background: #f5f7fa;
      color: #909399;
    }

    .image-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.6);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      opacity: 0;
      transition: opacity 0.3s;

      .el-icon {
        color: white;
        font-size: 16px;
        cursor: pointer;
        padding: 4px;
        border-radius: 2px;
        transition: background-color 0.3s;

        &:hover {
          background: rgba(255, 255, 255, 0.2);
        }

        &.sortable-drag {
          cursor: move;
        }
      }
    }

    &:hover .image-mask {
      opacity: 1;
    }
  }

  .upload-wrapper {
    position: relative;
    display: inline-block;
  }

  .upload-trigger {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px dashed #dcdfe6;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.3s;
    background: #fafafa;

    &:hover:not(.is-uploading) {
      border-color: var(--el-color-primary);
    }

    &.is-uploading {
      cursor: not-allowed;
      border-color: var(--el-color-primary);
      border-style: solid;
      background: var(--el-color-primary-light-9);
      animation: uploadingBorder 2s ease-in-out infinite;
    }

    .upload-icon {
      font-size: 24px;
      color: #8c939d;
      margin-bottom: 4px;
      transition: all 0.3s;
    }

    .upload-text {
      font-size: 12px;
      color: #8c939d;
      transition: all 0.3s;
      text-align: center;
    }
  }

  .upload-loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 6px;
    backdrop-filter: blur(2px);

    .loading-spinner {
      width: 20px;
      height: 20px;
      border: 2px solid #e4e7ed;
      border-top: 2px solid var(--el-color-primary);
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin-bottom: 8px;
    }

    .loading-text {
      font-size: 12px;
      color: var(--el-color-primary);
      font-weight: 500;
    }
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }

  @keyframes uploadingBorder {
    0% {
      border-color: var(--el-color-primary);
      box-shadow: 0 0 0 0 var(--el-color-primary-light-7);
    }

    50% {
      border-color: var(--el-color-primary-light-3);
      box-shadow: 0 0 0 4px var(--el-color-primary-light-8);
    }

    100% {
      border-color: var(--el-color-primary);
      box-shadow: 0 0 0 0 var(--el-color-primary-light-7);
    }
  }

  .upload-tip {
    margin-top: 8px;
    font-size: 12px;
    color: #909399;
    line-height: 1.4;
  }

  /* 精简模式样式 */
  .compact-mode {
    border: 1px solid #dcdfe6;
    border-radius: 4px;

    &:hover {
      border-color: var(--el-color-primary);
    }
  }

  .compact-mask {
    background: transparent;
    pointer-events: none;

    .el-icon {
      position: absolute;
      top: 2px;
      right: 2px;
      background: rgba(0, 0, 0, 0.8);
      border-radius: 50%;
      padding: 1px;
      pointer-events: auto;
      width: 16px;
      height: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
    }
  }

  .compact-trigger {
    border: 1px dashed #dcdfe6;
    border-radius: 4px;
    background: #fafafa;
    transition: all 0.3s;

    &:hover {
      border-color: var(--el-color-primary);
      background: var(--el-color-primary-light-9);
    }

    .upload-icon {
      color: #8c939d;
    }

    &:hover .upload-icon {
      color: var(--el-color-primary);
    }
  }
}
</style>
