/**
 * THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 */
import { useState, useEffect, useCallback } from 'react';
import { Upload, Modal, message } from 'antd';
import gadmin from '@/gadmin';
import { PlusOutlined } from '@ant-design/icons';
import { getFileName, parseFileSize } from '@/generated/utils';

function getBase64(file: Blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}

export type ImageUploadProps = {
  value?: string;
  fieldProps?: Record<string, any>;
  onChange?: (_value: any) => void;
  path?: string;
};

type PreviewInfo = {
  visible: boolean;
  image?: string;
  title?: string;
};

const ImageUpload = (props: ImageUploadProps) => {
  const [fileList, setFileList] = useState<any[]>([]);
  const [preview, setPreview] = useState<PreviewInfo>({ visible: false });

  const { onChange } = props;
  const handleChange = useCallback(
    (event: any) => {
      // 刚上传完成，提取url字段用于支持预览
      setFileList(
        event.fileList.map((item: any) => {
          if (!item.url && item.response) {
            Object.assign(item, { url: item.response.data?.url });
          }
          return item;
        }),
      );

      // 只在上传完成或删除完成时触发更新以免重复请求
      if (['done', 'removed'].includes(event.file.status)) {
        const fileUrlList = event.fileList
          .filter((e: any) => {
            return (
              (e.status === 'done' && !e.response) ||
              (e.response && e.response.code === 0 && e.response.data)
            );
          })
          .map((e: any) => {
            if (e.response) {
              return e.response.data.url;
            }
            return e.url;
          });
        onChange?.(fileUrlList.join('|'));
      }
    },
    [onChange],
  );

  const beforeUpload = useCallback(
    (file) => {
      // size limit
      if (props.fieldProps?.maxSize) {
        const { humanFormat, bytes } = parseFileSize(props.fieldProps.maxSize);
        if (file.size > bytes) {
          message.error(`image size limits to ${humanFormat}`);
          return Upload.LIST_IGNORE;
        }
      }

      // width or height limit
      if (props.fieldProps?.width && props.fieldProps?.height) {
        const isSize = new Promise((resolve, reject) => {
          const url = window.URL || window.webkitURL;
          const img = new Image();
          img.onload = function imageOnload() {
            if (
              props.fieldProps?.width !== this.width ||
              props.fieldProps?.height !== this.height
            ) {
              reject(
                new Error(
                  `image size should be ${props.fieldProps?.width}x${props.fieldProps?.height}`,
                ),
              );
            } else {
              resolve(true);
            }
          };
          img.src = url.createObjectURL(file);
        }).then(
          () => file,
          (error) => {
            message.error(error.message);
            return Upload.LIST_IGNORE;
          },
        );
        return isSize;
      }

      return true;
    },
    [props.fieldProps?.maxSize, props.fieldProps?.width, props.fieldProps?.height],
  );

  const handlePreview = async (file: any) => {
    let previewImage = file.url;
    if (!file.url && !file.preview) {
      previewImage = await getBase64(file.originFileObj);
    }

    setPreview({
      visible: true,
      image: previewImage,
      title: file.name || getFileName(file.url),
    });
  };

  // 拆分文件列表
  useEffect(() => {
    if (props.value) {
      const initialFileList = props.value.split('|').map((e, i) => {
        return {
          uid: i,
          name: getFileName(e),
          status: 'done',
          url: e,
        };
      });
      setFileList(initialFileList);
    }
    // FIXME: onChange会更新props.value，所以依赖props.value会出现列表闪烁，故取消依赖
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const uploadButton = (
    <div>
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>Upload</div>
    </div>
  );

  return (
    <>
      <Upload
        accept="image/*"
        {...props.fieldProps}
        action={gadmin.uploadUrl()}
        headers={gadmin.uploadHeaders?.()}
        data={{ path: props.path || 'gadmin/images' }}
        fileList={fileList}
        listType="picture-card"
        onPreview={handlePreview}
        onChange={handleChange}
        beforeUpload={beforeUpload}
      >
        {props.fieldProps?.maxCount && fileList.length >= props.fieldProps.maxCount
          ? null
          : uploadButton}
      </Upload>
      <Modal
        visible={preview.visible}
        title={preview.title}
        footer={null}
        onCancel={() => setPreview({ visible: false })}
      >
        <img style={{ width: '100%' }} src={preview.image} alt={preview.title} />
      </Modal>
    </>
  );
};

export default ImageUpload;
