<script setup lang="ts">
/**
 * 媒体选择器：从相册选图并上传到 /admin/attachments/upload，回写 URL。
 * 作品封面、头像、附件库等复用，避免各表单重复实现上传。
 */
import { computed, ref } from 'vue'
import { useToast } from '@wot-ui/ui'
import { uploadAttachment } from '@/api'
import { resolveMediaUrl } from '@/utils/request'

const props = withDefaults(defineProps<{
  modelValue?: string
  label?: string
  mediaType?: 'image' | 'video' | 'all'
}>(), {
  modelValue: '',
  label: '图片',
  mediaType: 'image',
})

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

const toast = useToast()
const uploading = ref(false)

const preview = computed(() => resolveMediaUrl(props.modelValue))

async function choose() {
  try {
    if (props.mediaType === 'video') {
      const res = await uni.chooseVideo({ sourceType: ['album', 'camera'], compressed: true })
      await doUpload(res.tempFilePath)
      return
    }
    const res = await uni.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'] })
    const path = res.tempFilePaths?.[0]
    if (!path) return
    await doUpload(path)
  }
  catch (e: unknown) {
    // 用户取消不提示
    if (e && typeof e === 'object' && 'errMsg' in e && String((e as { errMsg: string }).errMsg).includes('cancel')) return
    toast.error(e instanceof Error ? e.message : '选择失败')
  }
}

async function doUpload(filePath: string) {
  uploading.value = true
  try {
    const result = await uploadAttachment(filePath)
    const url = String(result.fileUrl || result.url || '')
    if (!url) throw new Error('上传成功但未返回地址')
    emit('update:modelValue', url)
    toast.success('上传成功')
  }
  catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : '上传失败')
  }
  finally {
    uploading.value = false
  }
}

function clear() {
  emit('update:modelValue', '')
}
</script>

<template>
  <view class="media-picker">
    <text v-if="label" class="label text-art-muted">{{ label }}</text>
    <view class="box" @click="choose">
      <image v-if="preview && mediaType !== 'video'" class="preview" :src="preview" mode="aspectFill" />
      <view v-else-if="preview && mediaType === 'video'" class="video-hint">
        <text>已选视频</text>
        <text class="url text-art-muted">{{ modelValue }}</text>
      </view>
      <view v-else class="placeholder">
        <wd-loading v-if="uploading" />
        <text v-else class="text-art-muted">点击上传{{ label }}</text>
      </view>
    </view>
    <wd-button v-if="modelValue" size="small" plain @click.stop="clear">清除</wd-button>
  </view>
</template>

<style scoped lang="scss">
.media-picker { display: flex; flex-direction: column; gap: 12rpx; margin: 16rpx 0; }
.label { font-size: 24rpx; }
.box {
  width: 240rpx;
  height: 240rpx;
  border-radius: 16rpx;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.06);
  border: 1px dashed rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
}
.preview { width: 100%; height: 100%; }
.placeholder, .video-hint {
  padding: 16rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8rpx;
  font-size: 24rpx;
}
.url { font-size: 20rpx; word-break: break-all; max-width: 200rpx; }
</style>
