import { Button, Modal, Upload, message } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { FC, useMemo, useRef, useState } from "react";
import { RcFile, UploadFile, UploadProps } from "antd/es/upload";
import { getTokenInfo } from "@/utils";
import { DageUploadProps, DageUploadType } from "./types";
import { UploadOutlined } from "@ant-design/icons";
import "./index.scss";

const getBase64 = (file: RcFile): Promise<string> =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = (error) => reject(error);
  });

export const DageUpload: FC<DageUploadProps> = ({
  action,
  value,
  type = DageUploadType.IMG,
  maxCount = 9,
  maxSize = 5,
  tips,
  disabled,
  onUploaded,
  onUploading,
  onChange,
}) => {
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImage, setPreviewImage] = useState("");
  const [previewTitle, setPreviewTitle] = useState("");
  const [uploading, setUploading] = useState(false);
  const uploadListType = useMemo(() => {
    switch (type) {
      case DageUploadType.IMG:
        return "picture-card";
      default:
        return "text";
    }
  }, [type]);
  const isPictureCard = uploadListType === "picture-card";
  const uploadingFileNum = useRef(0);

  const beforeUpload = (file: RcFile) => {
    let pass = false;
    let passFileType = false;

    // 校验文件类型
    switch (type) {
      case DageUploadType.IMG:
        passFileType = ["image/jpeg", "image/png", "image/gif"].includes(
          file.type
        );
        if (!passFileType) {
          message.error("只支持png、jpg、gif和jpeg格式!");
        }
        break;
      case DageUploadType.MODEL:
        passFileType = file.name.indexOf(".4dage") > -1;
        if (!passFileType) {
          message.error("只支持4dage格式的模型文件!");
        }
        break;
      case DageUploadType.VIDEO:
        passFileType = ["video/mp4"].includes(file.type);
        if (!passFileType) {
          message.error("只支持mp4格式!");
        }
        break;
      case DageUploadType.AUDIO:
        passFileType = ["audio/mpeg"].includes(file.type);
        if (!passFileType) {
          message.error("只支持mp3格式!");
        }
        break;
    }

    // 校验文件大小
    const isLtM = file.size / 1024 / 1024 < maxSize;
    if (!isLtM) {
      message.error(`最大支持 ${maxSize}M!`);
    }

    uploadingFileNum.current += 1;
    pass = passFileType && isLtM;

    return pass ? pass : Upload.LIST_IGNORE;
  };

  const handleChange: UploadProps["onChange"] = ({
    fileList: newFileList,
    file,
  }) => {
    if (file.status === "uploading") {
      setUploading(true);
      onUploading?.();
    }
    if (file.status === "done") {
      uploadingFileNum.current -= 1;

      if (uploading && !uploadingFileNum.current) {
        setUploading(false);
        onUploaded?.();
      }
    }
    onChange?.(
      newFileList.map((i) => ({
        ...i,
        dType: type,
      }))
    );
  };

  const handleCancel = () => setPreviewOpen(false);

  const handlePreview = async (file: UploadFile) => {
    if (!isPictureCard) return;

    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj as RcFile);
    }

    setPreviewImage(file.url || (file.preview as string));
    setPreviewOpen(true);
    setPreviewTitle(
      file.name || file.url!.substring(file.url!.lastIndexOf("/") + 1)
    );
  };

  return (
    <div className="dage-upload">
      <Upload
        disabled={disabled}
        headers={{
          token: getTokenInfo().token,
        }}
        fileList={value}
        withCredentials
        action={process.env.REACT_APP_BACKEND_URL + action}
        name="file"
        listType={uploadListType}
        data={{
          type,
        }}
        maxCount={maxCount}
        showUploadList={{
          showDownloadIcon: true,
        }}
        multiple={maxCount > 1}
        onPreview={handlePreview}
        beforeUpload={beforeUpload}
        onChange={handleChange}
      >
        {!disabled &&
          (isPictureCard ? (
            (!value || value.length < maxCount) && <PlusOutlined />
          ) : (
            <Button icon={<UploadOutlined />}>上传</Button>
          ))}
      </Upload>

      {!!tips && (
        <p
          style={{ marginTop: isPictureCard ? 0 : "8px" }}
          className="dage-upload__tips"
        >
          {tips}
        </p>
      )}

      <Modal
        open={previewOpen}
        title={previewTitle}
        footer={null}
        onCancel={handleCancel}
      >
        <img alt="example" style={{ width: "100%" }} src={previewImage} />
      </Modal>
    </div>
  );
};

export * from "./types";
