import React, { useEffect, useState } from 'react';
import { message, Progress, 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';

export type FileUploadProps = PropsType;
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?: { url: string }[]; // 默认文件列表
  disabled?: boolean; // 是否禁用
  showUploadList?: 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,
    showUploadList: true,
  };
  const {
    fileType = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
    children,
    listType,
    fileSize,
    fileUpload,
    fileLength,
    onChange,
    defaultFileList,
    disabled,
  } = props;
  // 开始上传
  const [uploading, setUploading] = useState<boolean>(false);
  // 上传进度
  const [progress, setProgress] = useState(0);
  // 是否上传图片
  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: (options) => {
      if (fileList.length >= (fileLength || 1)) {
        message.error(`最多上传${fileLength || 1}个文件`).then();
        return;
      }
      if (fileUpload) {
        // 上传到服务器
        const formData = new FormData();
        formData.append('uploadFile', options.file);
        CommonAPI.uploadOssBP(formData, {
          onUploadProgress: ({ total, loaded }) => {
            // 计算上传的百分比
            const percent = Math.round((loaded / (total || 1)) * 100);
            // 调用onProgress回调函数
            options?.onProgress?.({ percent });
            // 更新进度条的状态
            setProgress(percent);
            // 开始上传
            setUploading(true);
          },
        }).then(({ result }: any) => {
          const arr = [
            ...fileList,
            {
              id: new Date().getTime(),
              uid: new Date().getTime(),
              name: (options.file as any).name,
              url: result,
            },
          ];
          setFileList(arr);
          onChange?.(arr);
          // 上传成功
          setUploading(false);
        });
      } else {
        setFileList([...fileList, options.file]);
        onChange?.([...fileList, options.file]);
      }
    },
    onRemove: (res) => {
      const newFileList = fileList.filter((item) => item.uid !== res.uid);
      setProgress(0);
      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 || uploading}
            showUploadList={props?.showUploadList}
          >
            <>{fileList.length < (fileLength || 1) && children}</>
          </Upload>
          {progress > 0 && uploading && (
            <Progress percent={progress} size={'small'} style={{ height: '50px' }} />
          )}
        </>
      ) : (
        <>
          <Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled || uploading}>
            {fileList.length < (fileLength || 1) && children}
          </Upload>
          {progress > 0 && uploading && (
            <Progress percent={progress} size={'small'} style={{ height: '50px' }} />
          )}
        </>
      )}
      <Viewer
        visible={visible}
        currentImgList={[
          {
            src: currentFile,
            alt: '图片',
          },
        ]}
        activeViewerIndex={0}
        setVisible={() => {
          setVisible(false);
        }}
      />
    </div>
  );
};
