<template>
  <a-upload
    :file-list="[]"
    :multiple="false"
    :before-upload="onBeforeUpload"
    :accept="extnames.map(ext => `.${ext}`).join(',')"
  >
    <a-button type="primary" :disabled="disabled || !!file">
      <upload-outlined></upload-outlined>
      上传
    </a-button>
  </a-upload>
  <ol class="desc">
    <li>支持{{ extxTip }}文件格式；</li>
    <li>最大支持上传{{ maxSizeTip }}；</li>
    <template v-if="tips">
      <li v-for="tip in tips" :key="tip">{{ tip }}</li>
    </template>
  </ol>
  <div v-if="file" class="action">
    <p>{{ typeof file === 'string' ? file : file.name }}</p>
    <delete-outlined
      v-if="!disabled"
      class="icon"
      @click="emit('update:file', undefined)"
    />
  </div>
</template>

<script lang="ts" setup>
import { message } from 'ant-design-vue'
import { getExtname } from '@/shared'
import { computed } from 'vue'

import type { UploadProps } from 'ant-design-vue'

export type BUploadProps = {
  disabled?: boolean
  file?: File | string
  maxSize: number
  extnames: string | string[]
  tips?: string[]
}

const props = defineProps<BUploadProps>()

const emit = defineEmits<{
  (e: 'update:file', v: BUploadProps['file']): void
}>()

const maxMB = computed(() => props.maxSize * 1024 * 1024)
const maxSizeTip = computed(() =>
  props.maxSize > 1024 ? props.maxSize / 1024 + 'GB' : props.maxSize + 'MB'
)
const extnames = computed(() =>
  (Array.isArray(props.extnames) ? props.extnames : [props.extnames]).map(ext =>
    ext.toLowerCase()
  )
)
const extxTip = computed(
  () =>
    extnames.value.map(ext => `.${ext}`).join('、') +
    (extnames.value.length > 1 ? '等' : '')
)

const onBeforeUpload: UploadProps['beforeUpload'] = file => {
  const ext = getExtname(file.name)?.toLocaleLowerCase()

  if (!ext || !extnames.value.includes(ext)) {
    message.error(`仅支持${extxTip.value}文件格式`)
  } else if (file.size > maxMB.value) {
    message.error(`最大支持上传${maxSizeTip.value}`)
  } else {
    emit('update:file', file)
  }
  return false
}
</script>

<style lang="scss" scoped>
.desc {
  margin-top: 16px;
  color: #999999;
  padding-left: 20px;
}

.action {
  font-size: 14px;
  color: #323233;
  display: flex;
  align-items: center;
  p {
    margin: 0;
    word-break: break-all;
  }
  .icon {
    margin-left: 10px;
    color: #c8c8c8;
    cursor: pointer;
    transition: color 0.3s ease;

    &:hover {
      color: inherit;
    }
  }
}
</style>
