<template>
  <view class="image-uploader">
    <view class="uploader-list">
      <!-- 已上传图片 -->
      <view
        v-for="(image, index) in imageList"
        :key="index"
        class="uploader-item"
      >
        <image
          :src="image.url || image"
          class="uploader-image"
          mode="aspectFill"
          @tap="handlePreview(index)"
        ></image>

        <!-- 上传中 -->
        <view v-if="image.loading" class="uploader-loading">
          <u-loading-icon :show="true" :size="40" color="#FFFFFF"></u-loading-icon>
        </view>

        <!-- 删除按钮 -->
        <view v-if="!disabled && !image.loading" class="uploader-delete" @tap.stop="handleDelete(index)">
          <u-icon name="close-circle-fill" :size="36" color="#FF4D4F"></u-icon>
        </view>
      </view>

      <!-- 上传按钮 -->
      <view
        v-if="showUploadButton"
        class="uploader-item uploader-button"
        @tap="handleChoose"
      >
        <u-icon name="camera" :size="48" color="#CCCCCC"></u-icon>
        <text class="uploader-text">{{ uploadText }}</text>
        <text v-if="maxCount > 0" class="uploader-count">{{ imageList.length }}/{{ maxCount }}</text>
      </view>
    </view>

    <!-- 提示文字 -->
    <view v-if="tip" class="uploader-tip">
      <text>{{ tip }}</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'

interface ImageItem {
  url: string
  loading?: boolean
  [key: string]: any
}

interface Props {
  modelValue?: (string | ImageItem)[]  // 图片列表
  maxCount?: number                     // 最大数量
  maxSize?: number                      // 最大尺寸（MB）
  disabled?: boolean                    // 是否禁用
  uploadText?: string                   // 上传按钮文字
  tip?: string                          // 提示文字
  sizeType?: ('original' | 'compressed')[]  // 图片尺寸
  sourceType?: ('album' | 'camera')[]  // 图片来源
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  maxCount: 9,
  maxSize: 10,
  disabled: false,
  uploadText: '上传图片',
  sizeType: () => ['compressed'],
  sourceType: () => ['album', 'camera']
})

const emit = defineEmits<{
  'update:modelValue': [value: (string | ImageItem)[]]
  'change': [value: (string | ImageItem)[]]
  'upload': [file: any, index: number]
  'delete': [index: number]
  'preview': [index: number]
}>()

const imageList = ref<(string | ImageItem)[]>(props.modelValue || [])

// 是否显示上传按钮
const showUploadButton = computed(() => {
  if (props.disabled) return false
  if (props.maxCount <= 0) return true
  return imageList.value.length < props.maxCount
})

// 监听外部值变化
watch(() => props.modelValue, (val) => {
  imageList.value = val || []
}, { deep: true })

// 选择图片
const handleChoose = () => {
  if (props.disabled) return

  const count = props.maxCount > 0 ? props.maxCount - imageList.value.length : 9

  uni.chooseImage({
    count,
    sizeType: props.sizeType,
    sourceType: props.sourceType,
    success: (res) => {
      const tempFiles = res.tempFiles

      // 检查文件大小
      for (const file of tempFiles) {
        if (file.size > props.maxSize * 1024 * 1024) {
          uni.showToast({
            title: `图片大小不能超过${props.maxSize}MB`,
            icon: 'none'
          })
          return
        }
      }

      // 添加到列表
      const newImages = tempFiles.map((file) => ({
        url: file.path,
        loading: true
      }))

      imageList.value = [...imageList.value, ...newImages]
      emit('update:modelValue', imageList.value)
      emit('change', imageList.value)

      // 触发上传事件
      newImages.forEach((image, index) => {
        const actualIndex = imageList.value.length - newImages.length + index
        emit('upload', tempFiles[index], actualIndex)
      })
    }
  })
}

// 删除图片
const handleDelete = (index: number) => {
  uni.showModal({
    title: '提示',
    content: '确定要删除这张图片吗？',
    success: (res) => {
      if (res.confirm) {
        imageList.value.splice(index, 1)
        emit('update:modelValue', imageList.value)
        emit('change', imageList.value)
        emit('delete', index)
      }
    }
  })
}

// 预览图片
const handlePreview = (index: number) => {
  const urls = imageList.value.map((item) => {
    return typeof item === 'string' ? item : item.url
  })

  uni.previewImage({
    current: index,
    urls
  })

  emit('preview', index)
}

// 更新图片状态
const updateImage = (index: number, data: Partial<ImageItem>) => {
  const image = imageList.value[index]
  if (typeof image === 'object') {
    Object.assign(image, data)
  }
}

// 暴露方法
defineExpose({
  updateImage
})
</script>

<style lang="scss" scoped>
@import '@/static/styles/design-tokens.scss';
@import '@/static/styles/mixins.scss';

.image-uploader {
  width: 100%;
}

/* ========== 上传列表 ========== */
.uploader-list {
  display: flex;
  flex-wrap: wrap;
  gap: $spacing-md;
}

/* ========== 上传项 ========== */
.uploader-item {
  position: relative;
  width: 200rpx;
  height: 200rpx;
  border-radius: $radius-sm;
  overflow: hidden;
  background: $bg-page;
}

/* 图片 */
.uploader-image {
  width: 100%;
  height: 100%;
}

/* 上传中 */
.uploader-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  @include flex-center;
}

/* 删除按钮 */
.uploader-delete {
  position: absolute;
  top: 8rpx;
  right: 8rpx;
  width: 36rpx;
  height: 36rpx;
  @include flex-center;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  transition: $transition-all;

  &:active {
    transform: scale(0.9);
  }
}

/* ========== 上传按钮 ========== */
.uploader-button {
  @include flex-center;
  flex-direction: column;
  gap: $spacing-xs;
  border: 2rpx dashed $border-base;
  background: $bg-card;
  transition: $transition-all;

  &:active {
    background: $bg-hover;
    border-color: $primary-color;
  }
}

.uploader-text {
  font-size: $font-sm;
  color: $text-tertiary;
}

.uploader-count {
  font-size: $font-xs;
  color: $text-placeholder;
}

/* ========== 提示文字 ========== */
.uploader-tip {
  margin-top: $spacing-md;
  font-size: $font-sm;
  color: $text-tertiary;
  line-height: $line-height-normal;
}
</style>
