<template>
  <div class="image-uploader">
    <div class="upload-grid">
      <div
        v-for="(img, i) in images"
        :key="i"
        class="upload-item"
      >
        <van-image :src="img" width="100%" height="100%" fit="cover" radius="6" />
        <van-icon
          name="cross"
          class="remove-btn"
          @click="removeImage(i)"
        />
      </div>
      <div
        v-if="images.length < max"
        class="upload-item upload-add"
        @click="showAction = true"
      >
        <van-icon name="photograph" size="24" color="#999" />
        <span class="add-text">拍照</span>
      </div>
    </div>

    <van-action-sheet
      v-model:show="showAction"
      :actions="actions"
      cancel-text="取消"
      @select="onSelect"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { showToast } from 'vant'
import { takePhoto, pickFromAlbum } from '@/utils/camera'
import { uploadImage } from '@/api/upload'

const props = withDefaults(defineProps<{
  modelValue: string[]
  max?: number
}>(), { max: 9 })

const emit = defineEmits<{ 'update:modelValue': [v: string[]] }>()

const showAction = ref(false)
const uploading = ref(false)

const actions = [
  { name: 'camera', description: '拍摄照片' },
  { name: 'album', description: '从相册选择' },
]

const images = computedWithEmit()

function computedWithEmit() {
  return new Proxy(props.modelValue, {
    get: (_, key) => props.modelValue[key as any],
  })
}

function removeImage(i: number) {
  const arr = [...props.modelValue]
  arr.splice(i, 1)
  emit('update:modelValue', arr)
}

async function onSelect(action: { name: string }) {
  showAction.value = false
  if (uploading.value) return
  uploading.value = true

  try {
    const files = action.name === 'camera'
      ? [await takePhoto()]
      : await pickFromAlbum(props.max - props.modelValue.length > 1)

    showToast('上传中...')
    const urls = await Promise.all(files.map(uploadImage))
    emit('update:modelValue', [...props.modelValue, ...urls])
  } catch (err: any) {
    if (err.message !== '未选择图片') {
      showToast(err.message || '操作失败')
    }
  } finally {
    uploading.value = false
  }
}
</script>

<style scoped>
.upload-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.upload-item {
  position: relative;
  width: calc((100% - 24px) / 4);
  aspect-ratio: 1;
}
.upload-add {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px dashed #ddd;
  border-radius: 6px;
  background: #fafafa;
  cursor: pointer;
  gap: 2px;
}
.add-text {
  font-size: 11px;
  color: #999;
}
.remove-btn {
  position: absolute;
  top: -6px;
  right: -6px;
  background: rgba(0,0,0,0.5);
  color: #fff;
  border-radius: 50%;
  padding: 2px;
  font-size: 12px;
}
</style>
