<script setup lang="ts">
import type { UploadChangeParam } from 'ant-design-vue';

import { ref, watchEffect } from 'vue';

import { useRequest } from 'alova/client';
import { Modal, Upload } from 'ant-design-vue';

import { uploadFileMethod } from '#/api/method/common';

interface UploadFile extends File {
  uid?: string;
  status: 'done' | 'error' | 'removed' | 'success' | 'uploading';
  thumbUrl: string;
  url: string;
}

defineOptions({
  inheritAttrs: false,
});

function getBase64(img: Blob, callback: (base64Url: string) => void) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(reader.result as string), {
    once: true,
  });
  reader.readAsDataURL(img);
}

const { loading, send: upload } = useRequest(uploadFileMethod, {
  immediate: false,
});

const avatar = defineModel<string | void>('value', { default: void 0 });
const fileList = ref<UploadFile[]>([]);
watchEffect(() => {
  const url = avatar.value ?? '';
  if (url) {
    const name = url.split('/').pop() ?? 'avatar.png';
    fileList.value = [{ uid: '-1', status: 'done', name, url } as UploadFile];
  } else {
    fileList.value = [];
  }
});

const previewVisible = ref(false);
const previewImage = ref('');
const handleCancel = () => {
  previewVisible.value = false;
};
const onPreviewHandle = async (file: UploadFile) => {
  previewImage.value = file.url || file.thumbUrl;
  previewVisible.value = true;
};

const onChangeHandle = async (info: UploadChangeParam<UploadFile>) => {
  info.file.status ??= 'uploading';
  if (info.file.status === 'uploading') {
    getBase64(info.file, (thumbUrl) => {
      info.file.thumbUrl = thumbUrl;
    });
    try {
      const url = await upload(info.file);
      info.file.status = 'done';
      avatar.value = url;
    } catch {
      info.file.status = 'error';
      avatar.value = void 0;
    }
  }
};

const onRemoveHandle = () => {
  avatar.value = void 0;
};
</script>

<template>
  <div>
    <Upload
      v-bind="$attrs"
      v-model:file-list="fileList"
      accept="image/*"
      :max-count="1"
      name="avatar"
      list-type="picture-card"
      class="avatar-uploader"
      :disabled="loading"
      :before-upload="() => false"
      @change="onChangeHandle"
      @remove="onRemoveHandle"
      @preview="onPreviewHandle"
    >
      <div v-if="!fileList?.length" class="ant-upload-text">上传</div>
    </Upload>
    <Modal
      :open="previewVisible"
      title="图片预览"
      :footer="null"
      @cancel="handleCancel"
    >
      <img alt="example" style="width: 100%" :src="previewImage" />
    </Modal>
  </div>
</template>

<style scoped></style>
