<script setup lang="ts">
import { computed, onMounted, type PropType, reactive, ref, watch } from 'vue';

import { useAccessStore } from '@vben/stores';

import {
  Button,
  message,
  Upload,
  type UploadChangeParam,
  type UploadFile,
} from 'ant-design-vue';

import { FileApi } from '#/api';
import { Icon } from '#/components/icon';

type UploadParams = {
  allowSuffix: string;
  directory: string;
  folderId: Number | String;
  path: string;
};

defineOptions({
  name: 'Upload',
  inheritAttrs: false,
});
const props = defineProps({
  value: {
    type: [Number, String] as PropType<number | string>,
    default: 0,
  },
  action: {
    // 上传的地址
    type: String,
    default: `${import.meta.env.VITE_GLOB_API_URL}/file/upload`,
  },
  headers: {
    // 上传请求的 headers
    type: Object,
    default: () => ({}),
  },
  disabled: {
    // 是否禁用
    type: Boolean,
    default: false,
  },
  listType: {
    // 上传类型
    type: String as PropType<'picture' | 'picture-card' | 'text'>,
    default: 'text',
  },
  maxCount: {
    // 最大上传数量
    type: Number,
    default: undefined,
  },
  uploadName: {
    // 文件上传字段名,name被字段名覆写了，要换成uploadName
    type: String,
    default: undefined,
  },
  params: {
    type: Object as PropType<UploadParams>,
    default: () => ({}),
  },
});
const emits = defineEmits(['update:modelValue']);
const accessStore = useAccessStore();
const fileList = ref<UploadFile[]>([]);
// const attrs = useAttrs();
const bindProps = computed(() => {
  return {
    // ...omit(attrs, ['name']), // 'onChange','onInput', 'onBlur',
    ...props,
    name: props.uploadName || 'file',
  };
});
const getFileList = async (val: number | string | undefined) => {
  if (!val) {
    if (fileList.value.length > 0) fileList.value = [];
    return;
  }
  const data = await FileApi.getList(Number(val));
  fileList.value =
    data && data.length > 0
      ? data.map((item) => {
          return {
            uid: item.id.toString(),
            size: item.sizeKb,
            name: item.fileName,
            url: item.filePath,
          } as UploadFile;
        })
      : [];
};

const uploadParams = reactive<UploadParams>({
  allowSuffix: '',
  directory: '',
  folderId: 0,
  path: '',
});
const modelValue = computed({
  get() {
    return props.value;
  },
  set(val) {
    Object.assign(uploadParams, props.params, { folderId: val });
    emits('update:modelValue', val);
  },
});

const getHeaders = {
  Authorization: `Bearer ${accessStore.accessToken}`,
  ...props.headers,
};
const handleChange = (info: UploadChangeParam) => {
  if (info.file.status === 'done') {
    // 更新file-list当前file的uid
    // console.log('handleChange', info.file, fileList.value);
    if (info.file.response.code === 200) {
      fileList.value = fileList.value.map((item) => {
        if (item.uid === info.file.uid) {
          return {
            ...item,
            uid: info.file.response.data.id,
          };
        }
        return item;
      });
      modelValue.value = info.file.response.data.folderId;
    } else {
      fileList.value.splice(fileList.value.indexOf(info.file), 1);
      message.error(info.file.response.message);
    }
  } else if (info.file.status === 'error') {
    message.error(`${info.file.name} file upload failed.`);
  }
};

const handleRemove = async (file: UploadFile) => {
  // console.log('handleRemove', file, fileList.value);
  await FileApi.deleteDetail(Number(file.uid));
  fileList.value.splice(fileList.value.indexOf(file), 1);
  if (fileList.value.length === 0) {
    modelValue.value = 0;
  }
};

watch(
  () => props.value,
  async (val) => {
    await getFileList(val);
  },
);
onMounted(async () => {
  await getFileList(props.value);
});
</script>
<template>
  <Upload
    v-model:file-list="fileList"
    v-bind="bindProps"
    :action="action"
    :data="uploadParams"
    :disabled="disabled"
    :headers="getHeaders"
    :list-type="listType"
    :max-count="maxCount"
    @change="handleChange"
    @remove="handleRemove"
  >
    <template #default>
      <Icon
        v-if="listType === 'picture-card'"
        :size="24"
        icon="ant-design:plus-outlined"
      />
      <Button v-else>
        上传文件
        <template #icon>
          <Icon icon="ant-design:cloud-upload-outlined" />
        </template>
      </Button>
    </template>
    <template v-for="item in Object.keys($slots)" #[item]="data">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </Upload>
</template>
