import React, { Component } from 'react';
import { connect } from 'react-redux';
import message from 'components/message';
import JSZip from 'jszip';
import { uploadAssets } from 'utils/upload';
import styles from './index.less';
import EasyvProgress from 'components/EasyvProgress';
import IconWrapper from 'components/IconWrapper';
import { CheckOutlined, DeleteSquareOutlined, RedoOutlined } from '@easyv/react-icons';
import { Space } from '@easyv/antd';

interface IProps {
  tenantId: number;
  file: any;
  currentScreenId?: string;
  data?: any[];
  onComplete?: (id) => void;
  assets: any[];
  dataRequest?: any;
  isZip?: boolean;
  onRemove: (id) => void;
  fileId?: string;
}

interface IState {
  total: number;
  loaded: number;
  status: 'success' | 'exception' | 'normal' | 'active';
  errMessage: 'string' | null;
}

class ImportAssets extends Component<IProps, IState> {
  constructor(props) {
    super(props);
    this.state = {
      total: 0,
      loaded: 0,
      status: 'normal',
      errMessage: null,
    };
  }
  controller: any;

  componentDidMount() {
    this.props.currentScreenId === undefined && this.handleUpload();
  }

  componentDidUpdate(
    prevProps: Readonly<IProps>,
    prevState: Readonly<IState>,
    snapshot?: any,
  ): void {
    if (this.props.currentScreenId === prevProps.file.uid && this.state.status === 'normal') {
      this.handleUpload();
    }
  }

  handleUpload = async () => {
    this.setState({
      status: 'active',
    });
    const { file, data = [], assets = [], dataRequest, isZip = true } = this.props;
    const fileName = file.name;
    if (isZip) {
      JSZip.loadAsync(file)
        .then(async (zip) => {
          const uploadData = {};
          await Promise.all(
            data.map(async (item) => {
              uploadData[item.name] = await zip.file(item.file)?.async('string');
              return;
            }),
          );
          // 需要上传的数据，没有配置data的（字体文件）不需要上传数据
          if (data.length) {
            const result = await dataRequest(uploadData);
            if (!result || result.code) {
              this.controller && this.controller.abort();
              this.setState({
                status: 'exception',
                errMessage: result?.message || '上传失败',
              });
              return;
            }
          }

          let all = assets.reduce((all, item) => all.concat(this.getFilesFromZip(zip, item)), []);
          if (!window.appConfig.LOCAL && !/\/admin/.test(window.location.pathname)) {
            all = all.filter((d) => !/^components\//.test(d));
          }
          this.setState({
            total: all.length,
          });

          await Promise.all(
            all.map(async (key) => {
              const data = await zip.file(key)?.async('blob');
              if (!data) {
                return;
              }

              // 替换第三方组件的租户目录为当前租户
              key = key.replace(/^tenants\/\d+\//, () => `tenants/${this.props.tenantId}/`);

              return uploadAssets({ file: data, path: key, rename: false }).then(() => {
                this.setState((prev) => ({
                  loaded: prev.loaded + 1,
                }));
              });
            }),
          );

          this.setState({
            status: 'success',
          });
          this.props?.onComplete?.(file.uid);
          message.success(`${fileName} 上传成功`);
        })
        .catch((err) => {
          console.error(err);
          if (err && err.name != 'AbortError') {
            message.error(`${fileName} 上传失败`);
          }
          this.controller && this.controller.abort();
          this.setState({
            status: 'exception',
          });
          this.props?.onComplete?.(file.uid);
        });
    } else {
      // 非zip资源，目前可能存在的是font文件直接上传

      this.setState({
        total: 1,
      });

      try {
        const key = `${assets[0]}/${fileName}`;

        await uploadAssets({ file, path: key, rename: false }).then(() => {
          this.setState((prev) => ({
            loaded: prev.loaded + 1,
          }));
        });

        this.setState({
          status: 'success',
        });
        this.props?.onComplete?.(file.uid);
        message.success(`${fileName} 上传成功`);
      } catch (error) {
        message.error(`${fileName} 上传失败`);
        this.controller && this.controller.abort();
        this.props?.onComplete?.(file.uid);
        this.setState({
          status: 'exception',
        });
      }
    }
  };

  getFilesFromZip = (zip, folder) => {
    const fileList: string[] = [];
    zip.folder(folder).forEach((_relativePath, file) => {
      if (!file.dir) {
        fileList.push(file.name);
      }
    });
    return fileList;
  };

  componentWillUnmount() {
    this.controller && this.controller.abort();
  }

  onRestart = () => {
    const { status } = this.state;
    if (status == 'exception') {
      this.setState(
        {
          total: 0,
          loaded: 0,
          status: 'normal',
        },
        () => {
          this.handleUpload();
        },
      );
    }
  };

  onRemove = () => {
    const { file } = this.props;
    this.props?.onComplete?.(file.uid);
    this.props.onRemove(file.uid);
  };

  render() {
    const { total, loaded, status } = this.state;
    const { file } = this.props;
    const percent =
      status === 'success' && total === 0 ? 100 : loaded ? Math.round((loaded / total) * 100) : 0;

    return (
      <div>
        <EasyvProgress
          percent={percent}
          status={status}
          title={file.name}
          statusMsg={{
            exception: (
              <Space>
                <IconWrapper
                  icon={RedoOutlined}
                  style={{ marginRight: 4 }}
                  className={styles.restartIcon}
                  title="重试"
                  onClick={this.onRestart}
                />
                <IconWrapper
                  icon={DeleteSquareOutlined}
                  title="移除"
                  className={styles.closeIcon}
                  onClick={this.onRemove}
                />
              </Space>
            ),
            active: (
              <IconWrapper
                icon={DeleteSquareOutlined}
                title="移除"
                className={styles.closeIcon}
                onClick={this.onRemove}
              />
            ),
            normal: (
              <IconWrapper
                icon={DeleteSquareOutlined}
                title="移除"
                className={styles.closeIcon}
                onClick={this.onRemove}
              />
            ),
            success: (
              <Space>
                <IconWrapper icon={CheckOutlined} style={{ color: '#00A755', fontSize: 14 }} />
                <span className={styles.title}>导入成功</span>
              </Space>
            ),
          }}
        />
        {this.state.errMessage && (
          <div style={{ margin: '-15px 0 12px', color: '#eb515a' }}>{this.state.errMessage}</div>
        )}
      </div>
    );
  }
}

const mapStateToProps = ({ user }) => {
  const { userInfo } = user;

  return {
    tenantId: userInfo.tenantId,
  };
};

export default connect(mapStateToProps)(ImportAssets);
