<script lang="ts" setup>
import { ref, useAttrs, useSlots, watch } from 'vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import type { UploadConfig } from '../types';
import type { UUploadProps } from './types';

const props = withDefaults(defineProps<UUploadProps>(), {
  disabled: false,
  directory: false,
  modelValue: ''
});
const emits = defineEmits([
  'change',
  'update:value',
  'update:modelValue',
  'download',
  'drop',
  'preview',
  'remove',
  'reject'
]);
const attrs = useAttrs();
const slots = useSlots();
const fileList = ref<UploadFile[]>(props.value || []);
const config = ref<UploadConfig>(Object.assign(props.config || {}, attrs));
const handleRemove = (file: UploadFile) => {
  fileList.value = fileList.value.filter(item => item.uid !== file.uid);
  emits('remove', file);
  return true;
};

const handleBeforeUpload = (file: UploadFile, _fileList: UploadFile[]): boolean | Promise<any> => {
  if (config.value.compress && file.type?.startsWith('image/')) {
    // @todo 图片压缩
  }
  return true;
};
const handleChange: UploadProps['onChange'] = info => {
  if (info.file.status === 'done') {
    let resFileList = [...info.fileList];
    if (props.max) {
      resFileList = info.fileList.slice(-props.max);
    }

    resFileList = resFileList.map(file => {
      if (file.response) file.url = file.response.data;
      return file;
    });
    fileList.value = resFileList;
    // emits('change', { ...info, fileList: fileList.value });
    emits('update:value', fileList.value);
  }
};

const urlsToList = () => {
  const fileUrls = props.modelValue.split(',').filter(i => i);
  fileList.value && console.warn(...fileList.value);
  fileList.value = fileUrls.map((url, index) => {
    const filename = url.split('/').at(-1)?.split('\\').at(-1) || '';
    return {
      lastModified: Date.now(),
      uid: Date.now().toString() + index,
      name: filename,
      response: {
        status: 'success',
        code: 200,
        data: url
      },
      url
    };
  });
};

urlsToList();

watch(
  () => fileList.value,
  () => {
    const modelValue = fileList.value?.map(file => file.response?.data).join(',');
    emits('update:modelValue', modelValue);
    emits('change', modelValue);
    emits('update:value', fileList.value);
  },
  {
    deep: true
  }
);
</script>

<template>
  <a-upload
    v-model:file-list="fileList"
    v-bind="config"
    :action="url || config?.url"
    :disabled="disabled"
    :before-upload="handleBeforeUpload"
    @remove="handleRemove"
    @change="handleChange"
  >
    <div
      v-if="config?.listType === 'picture-card'"
      style="display: flex; flex-direction: column; align-items: center; justify-content: center"
    >
      <span style="margin: 1rem 0">+</span>
      <span>{{ config.btnText || 'upload' }}</span>
    </div>
    <a-button v-else v-bind="config?.btnProps">
      {{ config.btnText || 'upload' }}
    </a-button>
    <template v-for="(slot, name) in slots" :key="name" #[name]="slotProps">
      <slot :key="name" :name="name" v-bind="slotProps" />
    </template>
  </a-upload>
</template>

<style lang="scss" scoped></style>
