import { ElMessage } from "element-plus";
import { computed, ref, watchEffect } from "vue";
import mime from "mime";

export type UploadProps<T> = {
  maxSize: number;
  url?: string;
  formats: string[];
  upload?: (
    file: File,
    onPercentage: (percentage: number) => void
  ) => Promise<T>;
};

const defaultUpload = (
  file: File,
  onPercentage: (percentage: number) => void
) => {
  onPercentage(100);
};

export const useUpload = <T, K extends File | string>(
  props: UploadProps<T>
) => {
  const percentage = ref<number>();
  const size = computed(() => Math.floor(props.maxSize / 1024 / 1024) + "M");
  const format = computed(
    () =>
      `${props.formats.join("、")}${
        props.formats.length > 1 ? "等" : ""
      }格式的文件`
  );
  const accept = computed(() =>
    props.formats
      .map((format) => {
        const index = format.indexOf(".");
        const ext = ~index ? format.substring(index + 1) : format;
        return mime.getType(ext) as string;
      })
      .join(", ")
  );
  const fileRef = ref<File | string | undefined>(props.url);

  const removeFile = () => {
    fileRef.value = undefined;
    return true;
  };
  const previewFile = () => {
    if (!fileRef.value) return;
    const url =
      typeof fileRef.value === "string"
        ? fileRef.value
        : URL.createObjectURL(fileRef.value);
    window.open(url);
  };

  const upload = async (file: File) => {
    console.log(file);
    const fileType = file.name
      .substring(file.name.lastIndexOf("."))
      .toUpperCase();

    if (!props.formats.some((type) => type.toUpperCase() === fileType)) {
      ElMessage.error(`请上传${format.value}`);
      return false;
    } else if (file.size > props.maxSize) {
      ElMessage.error(`请上传${size.value}以内的文件`);
      return false;
    } else {
      fileRef.value = file;
      await (props.upload || defaultUpload)(
        file,
        (val) => (percentage.value = val)
      );
      percentage.value = undefined;
      return true;
    }
  };

  return {
    file: fileRef,
    fileList: computed(() => {
      if (!fileRef.value) return [];
      if (typeof fileRef.value === "string") {
        return [
          {
            url: fileRef.value,
            name: fileRef.value.substring(fileRef.value.lastIndexOf("/") + 1),
          },
        ];
      } else {
        return [fileRef.value];
      }
    }),
    previewFile,
    removeFile,
    percentage,
    size,
    format,
    accept,
    upload,
  };
};
