import { Upload as AntdUpload, UploadProps, ConfigProvider } from 'antd';
import React, { useContext, useMemo, useState } from 'react';
import './index.less';
import classNames from 'classnames';
import { Icon } from '../Icon';
import {
  RcFile,
  ShowUploadListInterface,
  UploadFileStatus,
  UploadListType,
} from 'antd/lib/upload/interface';
import { DraggerProps } from 'antd/lib/upload';
import { Modal } from 'antd';

const { Dragger: AntDragger } = AntdUpload;

interface UploadExtraProps {
  pictureCardTips?: string;
}

export interface UploadFile<T = any> {
  uid: string;
  size?: number;
  name: string;
  fileName?: string;
  lastModified?: number;
  lastModifiedDate?: Date;
  url?: string;
  status?: UploadFileStatus;
  percent?: number;
  thumbUrl?: string;
  crossOrigin?: React.ImgHTMLAttributes<HTMLImageElement>['crossOrigin'];
  originFileObj?: RcFile;
  response?: T;
  error?: any;
  linkProps?: any;
  type?: string;
  xhr?: T;
  preview?: string;
}

interface RrenderItemProps {
  originNode: React.ReactElement<
    any,
    string | React.JSXElementConstructor<any>
  >;
  file: UploadFile<any>;
  fileList: UploadFile<any>[];
  actions: {
    download: () => void;
    preview: () => void;
    remove: () => void;
  };
  listType: UploadListType;
}

const statusIcon = {
  success: {
    color: 'var(--green-6)',
    icon: 'CheckOnCircleOne',
  },
  error: {
    color: 'var(--red-6)',
    icon: 'AttentionCircleOne',
  },
  uploading: {
    color: 'var(--primary-6)',
    icon: 'Loading',
    loading: true,
  },
  done: {
    color: 'var(--green-6)',
    icon: 'CheckOnCircleOne',
  },
};

const pngIcons = {
  excel: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/excel.png')}
    ></img>
  ),
  xlsx: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/excel.png')}
    ></img>
  ),
  xls: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/excel.png')}
    ></img>
  ),
  png: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/img.png')}
    ></img>
  ),
  jpeg: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/img.png')}
    ></img>
  ),
  pdf: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/pdf.png')}
    ></img>
  ),
  ppt: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/ppt.png')}
    ></img>
  ),
  pptx: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/ppt.png')}
    ></img>
  ),
  doc: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/word.png')}
    ></img>
  ),
  docx: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/word.png')}
    ></img>
  ),
  other: (
    <img
      style={{ width: '16px', height: '16px' }}
      src={require('./icons/other.png')}
    ></img>
  ),
};
const renderIcons = {
  text: {
    error: pngIcons,
    done: pngIcons,
    uploading: pngIcons,
  },
  'picture-card': {
    error: <Icon iconName="PictureError"></Icon>,
  },
};

const Upload = (props: UploadProps & UploadExtraProps) => {
  // 为了与 antd 的生态保持兼容性，我们要求必须要使用 `.@{ant-prefix}` 变量来生成类名
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('btri-upload');
  const { listType = 'text', pictureCardTips } = props;

  const renderItem = ({
    originNode,
    file,
    fileList,
    actions,
    listType,
  }: RrenderItemProps) => {
    const loadingCom = (
      <div
        style={{
          width: '100%',
          height: '120px',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          flexDirection: 'column',
          color: 'var(--primary-6)',
          border: '1px dashed var(--gray-blue-5)',
          backgroundColor: 'var(--gray-blue-1)',
          borderRadius: '4px',
        }}
      >
        <Icon style={{ fontSize: '24px' }} iconName="Loading" spin></Icon>
        <div style={{ marginTop: '8px' }}>
          上传中&nbsp;{file.percent?.toFixed(0)}%
        </div>
      </div>
    );
    const Items: any = {
      text: {
        showOriginNodeInLoading: true,
        statusIcon,
      },
      picture: {
        showOriginNodeInLoading: true,
      },
      'picture-card': {
        showOriginNodeInLoading: false,
        loadingCom,
      },
    };

    return (
      <div className={classNames(`${prefixCls}-upload-item`)}>
        {Items[listType].showOriginNodeInLoading
          ? originNode
          : file.status !== 'uploading' && originNode}
        {listType === 'text' && statusIcon[file.status] && (
          <Icon
            spin={file.status === 'uploading'}
            style={{ color: statusIcon[file.status].color }}
            iconName={statusIcon[file.status].icon}
            className={classNames(`${prefixCls}-status-icon`)}
          ></Icon>
        )}
        {file.status === 'uploading' && Items[listType]?.loadingCom}
      </div>
    );
  };

  const [visible, setVisible] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const _showUploadList = useMemo(() => {
    let resList: boolean | ShowUploadListInterface = false;
    const defaultList = {
      removeIcon: () => {
        return (
          <Icon
            iconName="Delete"
            style={{
              fontSize: '20px',
              color: listType === 'picture-card' && 'var(--white)',
            }}
          ></Icon>
        );
      },
      previewIcon: (file) => {
        return (
          <Icon
            iconName="PreviewOpen"
            style={{
              fontSize: '20px',
              color: listType === 'picture-card' && 'var(--white)',
            }}
          ></Icon>
        );
      },
      downloadIcon: (
        <Icon
          iconName="Download"
          style={{
            fontSize: '20px',
            color: listType === 'picture-card' && 'var(--white)',
          }}
        ></Icon>
      ),
    };
    switch (props.showUploadList) {
      case false:
        resList = false;
        break;
      case true:
        resList = defaultList;
      default:
        resList = {
          ...defaultList,
          ...(props.showUploadList as ShowUploadListInterface),
        };
        break;
    }
    return resList;
  }, [props.showUploadList, listType]);

  return (
    <>
      <AntdUpload
        onPreview={(file) => {
          setPreviewImage(file.thumbUrl || file.url);
          (file.thumbUrl || file.url) && setVisible(true);
        }}
        iconRender={(file, listType) => {
          return (
            renderIcons[listType]?.[file.status]?.[file.name.split('.')[1]] ||
            renderIcons[listType]?.[file.status]?.['other'] ||
            renderIcons[listType]?.[file.status]
          );
        }}
        itemRender={(originNode, file, fileList, actions) =>
          renderItem({ originNode, file, fileList, actions, listType })
        }
        {...props}
        className={classNames(`${prefixCls}-box`, props.className)}
        showUploadList={_showUploadList}
      >
        {props.children}
        {listType === 'picture-card' && (
          <div className={classNames(`${prefixCls}-picture-card-tips`)}>
            {pictureCardTips}
          </div>
        )}
      </AntdUpload>
      <Modal
        open={visible}
        footer={null}
        bodyStyle={{ padding: 0, background: 'transparent' }}
        onCancel={() => {
          setVisible(false);
        }}
        width="60%"
        className="btri_upload_preview_modal"
      >
        <img src={previewImage} style={{ width: '100%' }}></img>
      </Modal>
    </>
  );
};

Upload.Dragger = (props: DraggerProps) => {
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('btri-upload-dragger');

  const _showUploadList = useMemo(() => {
    let resList: boolean | ShowUploadListInterface = false;
    const defaultList = {
      removeIcon: () => {
        return (
          <Icon
            iconName="Delete"
            style={{
              fontSize: '20px',
              color: 'var(--gray-7)',
            }}
          ></Icon>
        );
      },
      previewIcon: (file) => {
        return (
          <Icon
            onClick={(e) => {}}
            iconName="PreviewOpen"
            style={{
              fontSize: '20px',
              color: 'var(--gray-7)',
            }}
          ></Icon>
        );
      },
      downloadIcon: (
        <Icon
          iconName="Download"
          style={{
            fontSize: '20px',
            color: 'var(--gray-7)',
          }}
        ></Icon>
      ),
    };
    switch (props.showUploadList) {
      case false:
        resList = false;
        break;
      case true:
        resList = defaultList;
      default:
        resList = {
          ...defaultList,
          ...(props.showUploadList as ShowUploadListInterface),
        };
        break;
    }
    return resList;
  }, [props.showUploadList]);

  return (
    <AntDragger
      itemRender={(originNode, file, fileList, actions) => {
        return (
          <div className={classNames(`${prefixCls}-container`)}>
            {originNode}
            <Icon
              className="status-icon"
              style={{ color: statusIcon[file.status]?.color }}
              iconName={statusIcon[file.status]?.icon}
              spin={file.status === 'uploading'}
            ></Icon>
          </div>
        );
      }}
      iconRender={(file, listType) => {
        return (
          renderIcons[listType]?.[file.status]?.[file.name.split('.')[1]] ||
          renderIcons[listType]?.[file.status]?.['other'] ||
          renderIcons[listType]?.[file.status]
        );
      }}
      {...props}
      showUploadList={_showUploadList}
      className={classNames(`${prefixCls}-box`, props.className)}
    >
      {props.children || (
        <div style={{ padding: '43px 0' }}>
          <span style={{ color: 'var(--primary-6)' }}>点击上传</span>
          <span style={{ color: 'var(--caption-font)' }}>
            &nbsp;&nbsp;/&nbsp;&nbsp;拖拽到此区域内
          </span>
        </div>
      )}
    </AntDragger>
  );
};

Upload.LIST_IGNORE = AntdUpload.LIST_IGNORE;

export { Upload };
