import { DeleteOutlined, EyeOutlined, PlusOutlined } from '@ant-design/icons';
import { Modal, Upload, notification, Spin } from 'antd';
import React, { useState, useEffect, useRef, forwardRef } from 'react';
import lodash from 'lodash';
import { ReactSortable } from 'react-sortablejs';
import { merchantUpload } from './service.js';
import styles from './style.less';

const MAX_FILE_SIZE = 5;
const UNIT = 1024 * 1024;

const UploadButton = (
  <div>
    <PlusOutlined />
    <div style={{ marginTop: 8 }}>上传图片</div>
  </div>
);

const UploadImage = forwardRef((props, ref) => {
  const {
    name = `${Date.now()}`,
    limit = null,
    multiple = true,
    disabled,
    uploadParams,
    value,
    width = 0,
    height = 0,
    accept = ['jpg', 'jpeg', 'png'],
  } = props;
  const [uploadLoading, setUploadLoading] = useState(false);
  const [previewVisible, setPreviewVisible] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const [previewTitle, setPreviewTitle] = useState('');
  const [fileList, setFileList] = useState([]);
  const [activeImgIndex, setActiveImgIndex] = useState(null);
  const fileListRef = useRef([]);

  useEffect(() => {
    const newPictures = (value || []).map((url, ind) => ({
      url,
      name: url,
      uid: `${ind}`,
    }));
    fileListRef.current = [...newPictures];
    setFileList([...newPictures]);
  }, [value]);

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

  const handlePreview = async file => {
    setPreviewImage(file.url);
    setPreviewVisible(true);
    setPreviewTitle(file.name || file.url.substring(file.url.lastIndexOf('/') + 1));
  };

  const bundleChange = imgFile => {
    const imgList = imgFile.map(item => item.url);
    props.onChange(imgList);
  };

  const handleRemove = file => {
    const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);
    bundleChange(freshFiles);
  };
  const checkFile = file =>
    new Promise(resolve => {
      const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
      if (!accept.includes(curType)) {
        notification.open({
          message: file.name,
          description: `图片格式须为${accept.join('、')}！`,
        });
        return resolve(null);
      }
      if (file.size > MAX_FILE_SIZE * UNIT) {
        notification.open({
          message: file.name,
          description: `单个图片大小不能超过${MAX_FILE_SIZE}M！`,
        });
        return resolve(null);
      }
      return resolve(file);
    });

  const imageLoading = (file, ret) =>
    new Promise(resolve => {
      const reader = new FileReader();
      // 监听图片转换完成
      reader.addEventListener(
        'load',
        () => {
          const temFile = { uid: file.uid, status: 'done', name: file.name, url: ret };
          resolve(temFile);
        },
        false,
      );
      reader.readAsDataURL(file);
    });

  const getImageSize = async file =>
    new Promise((resolve, reject) => {
      const fileObj = file;
      // 获取上传的图片的宽高
      const reader = new FileReader();
      reader.readAsDataURL(fileObj);
      reader.onload = evt => {
        const replaceSrc = evt.target.result;
        const imageObj = new Image();
        imageObj.src = replaceSrc;
        imageObj.onload = () => {
          const { width: widthPx, height: heightPx } = imageObj;
          file.width = widthPx;
          file.height = heightPx;
          resolve(file);
        };
      };
      reader.onerror = error => reject(error);
    });

  const validateImageSize = async files => {
    const fileAll = files.map(item => getImageSize(item));
    const checkFiles = (await Promise.all(fileAll)).filter(item => item !== null);
    const checkSize = checkFiles.some(
      item => (item.width !== width && width !== 0) || (item.height !== height && height !== 0),
    );
    if (checkSize) {
      notification.warning({ message: '图片尺寸不正确' });
      return false;
    }
    return true;
  };

  const defaultBeforeUpload = lodash.debounce(
    (file, fileArray) =>
      // 文件显示
      new Promise(async () => {
        if (limit && fileListRef.current.length + fileArray.length > limit) {
          Modal.warning({
            maskClosable: true,
            title: '超出上传个数',
          });
          return Upload.LIST_IGNORE;
        }
        if (width !== 0 || height !== 0) {
          const checkSize = await validateImageSize(fileArray);
          if (!checkSize) {
            return Upload.LIST_IGNORE;
          }
        }
        const fileAll = fileArray.map(item => checkFile(item));
        const checkFiles = (await Promise.all(fileAll)).filter(item => item !== null);
        try {
          if (checkFiles.length) {
            setUploadLoading(true);
            const res = await merchantUpload(checkFiles);
            if (res?.data) {
              const proFiles = (res.data || []).map((urlItem, urlIndex) =>
                imageLoading(checkFiles[urlIndex], urlItem),
              );
              const imagList = await Promise.all(proFiles);
              const newFiles = [...fileListRef.current, ...imagList];
              bundleChange(newFiles);
            } else {
              notification.warning({
                message: '警告',
                description: res?.msg || '上传失败，请重新尝试！',
              });
            }
            setUploadLoading(false);
          }
        } catch (error) {
          setUploadLoading(false);
          Modal.warning({
            maskClosable: true,
            title: '上传失败，请重新尝试！',
          });
        }
        return null;
      }),
  );
  return (
    <Spin tip="正在上传..." spinning={uploadLoading} delay={100}>
      <div>
        {fileList.length > 0 && (
          <ReactSortable animation={300} list={fileList} setList={list => bundleChange(list)}>
            {fileList.map((item, index) => (
              <div
                key={item.uid}
                className={styles.sortImg}
                onMouseEnter={() => setActiveImgIndex(index)}
                onMouseLeave={() => setActiveImgIndex(null)}
              >
                <div style={{ width: '100%', height: '100%', overflow: 'hidden' }}>
                  <img width="100%" key={item.uid} src={item.url} alt="" />
                </div>
                {activeImgIndex === index && (
                  <div className={styles.mask}>
                    <EyeOutlined className={styles.maskIcon} onClick={() => handlePreview(item)} />
                    <DeleteOutlined
                      className={styles.maskIcon}
                      onClick={() => handleRemove(item)}
                    />
                  </div>
                )}
              </div>
            ))}
          </ReactSortable>
        )}
      </div>

      <Upload
        {...uploadParams}
        disabled={Boolean(disabled)}
        multiple={multiple}
        name={name}
        customRequest={() => {}}
        listType="picture-card"
        beforeUpload={defaultBeforeUpload}
        fileList={fileList}
        onPreview={handlePreview}
        onRemove={handleRemove}
        showUploadList={false}
      >
        {limit !== null && fileList.length >= limit ? null : UploadButton}
      </Upload>
      <Modal open={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}>
        <img alt="example" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </Spin>
  );
});

export default UploadImage;
