import React, { useEffect, useState } from 'react';
import { message, Upload, UploadProps } from 'antd';
import { CommonAPI } from '~/api';
import './index.scss';
import Viewer from '~/components/viewer';
import saveAs from 'file-saver';
import { fileTypeList } from '~/utils/dictionary';

interface PropsType {
  listType?: 'text' | 'picture' | 'picture-card'; // 上传列表的内建样式
  fileSize?: number; // 文件大小
  fileType?: string[]; // 上传文件类型
  fileUpload: boolean; // 是否上传到服务器(返回文件流还是返回上传后的地址)
  fileLength?: number; // 最大上传文件数量
  children: React.ReactNode; // 上传按钮
  onChange?: (
    fileList: {
      id: number;
      name: string;
      uid: number;
      url: string;
    }[],
  ) => void; // 上传文件改变时的状态
  defaultFileList?: any[]; // 默认文件列表
  disabled?: boolean; // 是否禁用
}
export const Uploader: React.FC<PropsType> = (props) => {
  Uploader.defaultProps = {
    listType: 'picture-card',
    fileSize: 10,
    fileLength: 1,
    fileType: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'],
    defaultFileList: [],
    disabled: false,
  };
  const {
    fileType = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
    children,
    listType,
    fileSize,
    fileUpload,
    fileLength,
    onChange,
    defaultFileList,
    disabled,
  } = props;
  // 是否上传图片
  const [visible, setVisible] = useState<boolean>(false);
  // 当前选择的文件
  const [currentFile, setCurrentFile] = useState<string>();
  // 文件列表
  const [fileList, setFileList] = useState<any[]>([]);
  // 上传文件配置
  const uploadProps: UploadProps = {
    listType,
    fileList,
    beforeUpload: (res) => {
      // console.log('文件类型-->', res);
      const isType = fileType?.includes(res.type);
      const isSize = res.size / 1024 / 1024 < (fileSize || 2);
      if (!isType) {
        message.error(`请上传${getFileTypeStr()}格式的文件!`).then();
        return isType;
      }
      if (!isSize) {
        message.error(`文件最大${props.fileSize}M，请压缩后上传！`).then();
        return isSize;
      }
    },
    customRequest: (res) => {
      if (fileList.length >= (fileLength || 1)) {
        message.error(`最多上传${fileLength || 1}个文件`).then();
        return;
      }
      if (fileUpload) {
        // 上传到服务器
        const formData = new FormData();
        formData.append('uploadFile', res.file);
        CommonAPI.uploadOssBP(formData).then(({ result }) => {
          setFileList([
            ...fileList,
            {
              id: new Date().getTime(),
              uid: new Date().getTime(),
              name: (res.file as any).name,
              url: result,
            },
          ]);
          onChange?.([
            ...fileList,
            {
              id: new Date().getTime(),
              uid: new Date().getTime(),
              name: (res.file as any).name,
              url: result,
            },
          ]);
        });
      } else {
        setFileList([...fileList, res.file]);
        onChange?.([...fileList, res.file]);
      }
    },
    onRemove: (res) => {
      const newFileList = fileList.filter((item) => item.uid !== res.uid);
      setFileList(newFileList);
      onChange?.(newFileList);
    },
    onPreview: (res) => {
      const { url } = res;
      const fileType = url?.substring(url?.lastIndexOf('.') + 1) || '';
      if (['png', 'jpg', 'bmp', 'gif', 'jpeg', 'webp'].includes(fileType)) {
        setCurrentFile(url);
        setVisible(true);
      } else {
        if (url) {
          // 如果有oss地址,则直接下载
          saveAs(url.replace(/^http:/, 'https:'), res?.name ? res.name : '未命名文件');
        } else {
          // 没有就直接保存文件
          const blob = new Blob([res as any]);
          saveAs(blob, res.name);
        }
      }
    },
  };

  // 获取文件类型提示
  const getFileTypeStr = () =>
    fileType
      .map((v) => fileTypeList.find((i) => i.value === v)?.label)
      .filter((v) => !!v)
      .join(',');
  useEffect(() => {
    // 如果有默认文件列表
    if (defaultFileList?.length) {
      setFileList(defaultFileList);
    } else {
      setFileList([]);
    }
  }, [defaultFileList]);
  return (
    <div className='uploader-view'>
      {listType === 'text' ? (
        <Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled}>
          <>{fileList.length < (fileLength || 1) && children}</>
        </Upload>
      ) : (
        <Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled}>
          {fileList.length < (fileLength || 1) && children}
        </Upload>
      )}
      <Viewer
        visible={visible}
        currentImgList={[
          {
            src: currentFile,
            alt: '图片',
          },
        ]}
        activeViewerIndex={0}
        setVisible={() => {
          setVisible(false);
        }}
      />
    </div>
  );
};
