<template>
  <div class="simpleUploadDiv">
    <a-progress v-if="uploading" type="circle" :percent="percent" />
    <a-image height="80%" v-else :src="minioBaseUrl + modelValue" alt="avatar" />
    <a-button class="btn-success" @click="selectFile">{{ btnLabel }}</a-button>
    <input id="myFileInput" type="file" style="display: none" />
  </div>
</template>

<script setup lang="ts">
import { message } from 'ant-design-vue'
import { onMounted, onUnmounted, ref } from 'vue'
import { generateSimpleObjectName, getResignedObjectUrl } from '@/utils/minioUtil'
import axios, { CancelTokenSource } from 'axios'
import { convertFileSizeToStr } from '@/utils/index.ts'

const minioBaseUrl = __APP_ENV.VITE_APP_MINIO_URL

const modelValue = defineModel<string>('value')
const props = withDefaults(
  defineProps<{
    parentDir?: string
    allowedExtensions?: string[]
    maxSize?: number
    width?: string | number
    height?: string | number
    btnLabel?: string
  }>(),
  {
    parentDir: '',
    allowedExtensions: () => ['jpg', 'jpeg', 'png', 'gif'],
    maxSize: 1024 * 1024 * 4,
    width: '150px',
    height: '150px',
    btnLabel: '选择图片',
  }
)

const uploading = ref(false)
const percent = ref(0)
let cancelToken: CancelTokenSource | null = null

const selectFile = () => {
  document.getElementById('myFileInput')?.click()
}

async function inputFileListener(this: HTMLInputElement) {
  const selectedFile: File = this.files?.[0] as File

  const fileExtension = selectedFile?.name?.split('.')?.pop()?.toLowerCase() as string
  if (!props.allowedExtensions.includes(fileExtension)) {
    return message.error(`错误：不支持的文件格式,目前支持:【${props.allowedExtensions}】`)
  }

  const isMax = selectedFile.size > props.maxSize
  if (isMax) {
    return message.error(`文件大小超出限制，最大支持:【${convertFileSizeToStr(props.maxSize)}】`)
  }

  cancelToken?.cancel()
  percent.value = 0
  uploading.value = true

  const objectName = generateSimpleObjectName(selectedFile.name, props.parentDir)
  const uploadUrl = await getResignedObjectUrl(__APP_ENV.VITE_APP_MINIO_BUCKET, objectName)
  cancelToken = axios.CancelToken.source()
  await axios.put(uploadUrl, selectedFile, {
    cancelToken: cancelToken.token,
    onUploadProgress: (progressEvent) => {
      percent.value = ((progressEvent.loaded / (progressEvent.total as number)) * 100) | 0
    },
  })

  modelValue.value = '/' + __APP_ENV.VITE_APP_MINIO_BUCKET + objectName
  uploading.value = false
}

onMounted(() => {
  document.getElementById('myFileInput')?.addEventListener('change', inputFileListener)
})

onUnmounted(() => {
  document.getElementById('myFileInput')?.removeEventListener('change', inputFileListener)
})
</script>

<style scoped lang="scss">
.simpleUploadDiv {
  width: v-bind(width);
  height: v-bind(height);
  display: flex;
  flex-direction: column;
}
</style>
