<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>
      {{ $t('sys.uploadBtn') }}
    </a-button>
  </a-upload>
  <ol class="desc">
    <li>{{ $t('sys.uploadDesc[0]', { extxTip }) }}</li>
    <li>{{ $t('sys.uploadDesc[1]', { 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'
import { ui18n } from '@/lang'

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 ? ui18n.t('sys.more') : '')
)

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

  if (!ext || !extnames.value.includes(ext)) {
    message.error(ui18n.t('sys.noUploadDesc[0]', { extxTip: extxTip.value }))
  } else if (file.size > maxMB.value) {
    message.error(
      ui18n.t('sys.noUploadDesc[1]', { maxSizeTip: 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 {
    font-size: 1.2em;
    margin-left: 10px;
    color: #ff4d4f;
    cursor: pointer;
    transition: color 0.3s ease;

    &:hover {
      color: #ff7875;
    }

    &:active {
      color: #d9363e;
    }
  }
}
</style>
