<script lang="ts" setup>
import type {
  UploadFile,
  UploadFiles,
  UploadUserFile,
} from 'element-plus'
import { useAppUserStore } from '@/common/app/app-user-store.ts'
import { serverBaseUrl } from '@/common'
import { type R } from '@/common/utils/http-util.ts'
import Strings from '@/common/utils/strings.ts'
import AppApi from '@/common/app/app-api.ts'
import type { UploadProps } from 'element-plus/es/components/upload/src/upload'

const props = withDefaults(defineProps<{
  files?: string[]
  file?: string
  height?: string
  width?: string
  limit?: number
  disabled?: boolean
  uploadProps?: Partial<Omit<UploadProps, 'httpRequest' | 'crossorigin' | 'multiple'
    | 'data' | 'action' | 'headers' | 'limit' | 'onError'
    | 'onRemove' | 'onSuccess' | 'onPreview' | 'fileList' | 'beforeUpload' | 'beforeRemove' | 'onChange' | 'onProgress' | 'name' | 'drag'>>
}>(), {
  limit: 1,
  height: '100px',
  width: '100px',
  disabled: false,
  // @ts-ignore
  uploadProps: {
    // @ts-ignore
    listType: 'picture-card',
    accept: 'image/*',
  },
})

const multiple = computed(() => props.limit > 1)
const emit = defineEmits([ 'update:files', 'update:file' ])
const appUserStore = useAppUserStore()
const showPreview = ref(false)
const headers = computed(() => ({
  Authorization: appUserStore.token!,
}))
const uploadUrl = serverBaseUrl + '/oss/upload'

const filesList = ref<UploadUserFile[]>([])

const showUploadBtnDisplay = computed(() => {
  return multiple.value || filesList.value.length === 0 ? 'inline-flex' : 'none'
})

function uploadSuccHandler(response: R<string>, _: UploadFile, uploadFiles: UploadFiles) {
  if (props.limit === 1) {
    emit('update:file', response.data)
  } else {
    const urls = uploadFiles.filter(it => it.response != null && (it.response as R<string>).success).map(it => (it.response as R<string>).data)
    emit('update:files', urls)
  }
}

function rmFileHandler(_: UploadFile, uploadFiles: UploadFiles) {
  if (props.limit === 1) {
    if (uploadFiles.length > 0) {
      emit('update:file', (filesList.value[0].response as R<string>).data)
    } else {
      emit('update:file', undefined)
    }
  } else {
    const urls = uploadFiles.filter(it => it.response != null && (it.response as R<string>).success).map(it => (it.response as R<string>).data)
    emit('update:files', urls)
  }
}

function uploadFailHandler(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) {
  console.log(response, uploadFile, uploadFiles)
}

const previewList = computed(() => filesList.value.map(it => AppApi.fileUrl(it.url)))
const handlePictureCardPreview = () => {
  console.log(previewList.value, filesList.value)
  showPreview.value = true
}
defineExpose({
  setDefaultFiles(urls: string[]) {
    if (urls.length > 0) {
      for (let i = 0; i < urls.length; i++) {
        const url = urls[i]
        if (Strings.isBlank(url)) {
          continue
        }
        filesList.value?.push({
          uid: i,
          name: url.substring(url.lastIndexOf('/') + 1),
          url: AppApi.fileUrl(url),
          response: {code: 0, success: true, msg: '', message: '', data: url},
        })
      }
    }
  },
})

</script>

<template>
  <ElTooltip :disabled="showUploadBtnDisplay==='none'" content="点击或拖拽文件到此处" placement="top">
    <ElUpload
      v-model:file-list="filesList"
      :action="uploadUrl"
      :headers="headers"
      :limit="limit"
      :multiple="multiple"
      :on-error="uploadFailHandler"
      :on-preview="handlePictureCardPreview"
      :on-remove="rmFileHandler"
      :on-success="uploadSuccHandler"
      class="a-uploader"
      drag
      :disabled="disabled"
      v-bind="uploadProps">
      <slot>
        <ElIcon class="default-icon">
          <ElIconPlus/>
        </ElIcon>
      </slot>
    </ElUpload>
  </ElTooltip>
  <ElImageViewer
    v-if="showPreview"
    :url-list="previewList"
    show-progress
    teleported
    style="position: absolute"
    @close="showPreview = false"
  />
</template>

<style lang="stylus" scoped>
.a-uploader {
  width: v-bind(width);
  height: v-bind(height);

  :deep(.el-upload) {
    background-color white

    &.el-upload--picture-card {
      width: 100% !important;
      height: 100% !important;
    }


    &.el-upload--text,
    &.el-upload--picture,
    &.el-upload--picture-card {
      display v-bind(showUploadBtnDisplay)
    }

    &.el-upload--text,
    &.el-upload--picture {
      align-items: center;
      border: 1px dashed var(--el-border-color-darker)
      border-radius: 6px;
      box-sizing: border-box;
      cursor: pointer;
      height: var(--el-upload-picture-card-size);
      justify-content: center;
      vertical-align: top;
      width: var(--el-upload-picture-card-size);

      &:hover {
        border-color: var(--el-color-primary);
        color: var(--el-color-primary);
      }
    }
  }

  :deep(.el-upload-list) {
    margin 0
    width: 100%;
    height: 100%;

    .el-upload-list__item.is-success {
      margin 0
      width: 100%;
      height: 100%;
    }

    .el-upload-list__item.is-uploading {
      margin 0
      width: 100%;
      height: 100%;

      .el-progress {
        width 100%
        height 100%;

        .el-progress-circle {
          width 100% !important
          height 100% !important
        }

        .el-progress__text {
          width 100% !important
        }
      }
    }

    .el-upload-list__item.is-success:focus .el-upload-list__item-status-label {
      display: inline-flex !important;
      opacity: 1 !important;
    }

    .el-upload-list__item.is-success:hover .el-upload-list__item-status-label {
      display none !important;
      opacity 0 !important;
    }

  }

  :deep(.el-icon--close-tip) {
    display none !important;
  }

  :deep(.el-upload-list--picture) {
    .el-upload-list__item-info {
      flex: 1;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }


  :deep(.el-upload-dragger) {
    height: 100%;
    width: 100%;
    border: none;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .default-icon {
    color: var(--el-text-color-secondary);
    font-size: 28px;
  }
}
</style>
