import { PlusOutlined, DeleteOutlined, EyeOutlined } 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 ImgCrop from 'antd-img-crop';
import 'antd/es/modal/style';
import 'antd/es/slider/style';
import { merchantUpload } from '../service';
import styles from '../common.less';

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

const UploadCropImage = forwardRef((props, ref) => {
  const {
    name = `${Date.now()}`,
    limit = null,
    multiple = true,
    disabled,
    uploadParams,
    pictures = [],
    limitPicHeight = false,
    setPictureList = () => {},
    ...imgOptions
  } = 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 = pictures.map((url, ind) => ({
      url,
      name: url,
      uid: `${ind}`,
    }));
    fileListRef.current = [...newPictures];
    setFileList([...newPictures]);
  }, [pictures]);

  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 => {
    // setFileList(imgFile);
    const imgList = imgFile.map(item => item.url);
    setPictureList(imgList);
    props.onChange(imgList);
  };

  const handleRemove = file => {
    const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);
    bundleChange(freshFiles);
  };

  const cleanArray = (actual = []) =>
    actual.reduce((prev, cur) => {
      cur && prev.push(cur);
      return prev;
    }, []);

  const warningTip = description => {
    notification.warning({
      message: '图片上传失败',
      description,
    });
  };

  const getBase64 = (img, callback) => {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
  };

  const ImageInfo = file =>
    new Promise((resolve, reject) => {
      const LtMB = file.size / 1024 / 1024;
      if (LtMB > 2) {
        warningTip(`[${file.name}] 图片不可以大于2MB`);
        resolve(null);
      }
      getBase64(file, url => {
        const image = new Image();
        image.addEventListener('load', () => {
          const { width } = image;
          const { height } = image;
          file.width = width;
          file.height = height;
          file.LtMB = LtMB;
          resolve(file);
        });
        image.addEventListener('error', () => {
          warningTip(`${file.name}图片上传失败！`);
          resolve(null);
        });
        image.src = url;
      });
    });

  const CheckImageInfoList = async files => {
    const promiseImage = files.map(file => ImageInfo(file));
    const clearImage = await Promise.all(promiseImage);
    return cleanArray(clearImage);
  };

  const isUploadNext = async imgFileList => {
    const filterImage = imgFileList.filter(img => {
      if (
        (imgOptions.maxWidth && img.width > imgOptions.maxWidth) ||
        (imgOptions.maxHeight && img.height > imgOptions.maxHeight)
      ) {
        warningTip(`[${img.name}] ${imgOptions.superTips}`);
        return false;
      }
      return true;
    });
    return filterImage;
  };

  const checkFile = files => {
    const fileType = ['jpg', 'jpeg', 'png'];
    const filterImage = files.filter(file => {
      const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
      if (!fileType.includes(curType)) {
        warningTip('图片格式须为jpg、jpeg、png！');
        return false;
      }
      return true;
    });
    return filterImage;
  };

  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 defaultBeforeUpload = lodash.debounce(
    (file, fileArray) =>
      // 文件显示
      new Promise(async () => {
        console.log('defaultBeforeUpload :>> ', 11111);
        if (limit && fileListRef.current.length + fileArray.length > limit) {
          Modal.warning({
            maskClosable: true,
            title: '超出上传个数',
          });
          return Upload.LIST_IGNORE;
        }
        const flies = checkFile(fileArray);
        const optionsArray = await CheckImageInfoList(flies);
        const checkFiles = await isUploadNext(optionsArray);
        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) {
          console.log(error);
          setUploadLoading(false);
          Modal.warning({
            maskClosable: true,
            title: '上传失败，请重新尝试！',
          });
        }
        return null;
      }),
  );

  return (
    <Spin tip="正在上传..." spinning={uploadLoading} delay={100}>
      <div className={styles.imgContent}>
        {fileList.length > 0 && (
          <ReactSortable animation={300} list={fileList} setList={list => bundleChange(list)}>
            {fileList.map((item, index) => (
              <div
                // eslint-disable-next-line react/no-array-index-key
                key={index}
                className={styles.sortImg}
                onMouseEnter={() => setActiveImgIndex(index)}
                onMouseLeave={() => setActiveImgIndex(null)}
              >
                <div style={{ width: '90%', height: '90%', 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)} />
                    {!disabled && (
                      <DeleteOutlined
                        className={styles.maskIcon}
                        onClick={() => handleRemove(item)}
                      />
                    )}
                  </div>
                )}
              </div>
            ))}
          </ReactSortable>
        )}
      </div>
      {limit !== null && fileList.length >= limit ? (
        ''
      ) : (
        <ImgCrop
          rotationSlider
          modalWidth={500}
          quality={0.5}
          showReset
          showGrid
          resetText="重置"
          aspectSlider={!!limitPicHeight}
        >
          <Upload
            {...uploadParams}
            disabled={Boolean(disabled)}
            multiple={multiple}
            name={name}
            customRequest={() => {}}
            listType="picture-card"
            beforeUpload={defaultBeforeUpload}
            fileList={fileList}
            onPreview={handlePreview}
            onRemove={handleRemove}
            showUploadList={false}
          >
            {UploadButton}
          </Upload>
        </ImgCrop>
      )}
      <Modal visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}>
        <img alt="example" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </Spin>
  );
});

export default UploadCropImage;
