import { useNamespace } from '@ibiz-template/vue-util';
import { PropType, defineComponent, ref } from 'vue';
import '@ibiz-template/theme/style/components/common/data-import/data-import.scss';
import { HttpError } from '@ibiz-template/core';

export const DataImport = defineComponent({
  name: 'DataImport',
  props: {
    templateUrl: {
      type: String,
      required: true,
    },
    importUrl: {
      type: String,
      required: true,
    },
    dismiss: {
      type: Function as PropType<(_result: IParams) => void>,
    },
  },
  setup(props, { emit }) {
    const ns = useNamespace('data-import');
    const inputUpLoad = ref();
    const message = ref<{
      state: 'ready' | 'success' | 'fail';
      message: string;
      rowError: Array<{ index: number; info: string }>;
    }>({
      state: 'ready',
      message: '',
      rowError: [],
    });
    // 是否正在导入
    const isImporting = ref(false);

    // 上传数据
    const uploadFile = async (file: Blob) => {
      const data = new FormData();
      data.append('file', file);
      try {
        isImporting.value = true;
        const res = await ibiz.net.request(props.importUrl, {
          method: 'post',
          data,
          headers: { 'Content-Type': 'multipart/form-data' },
        });
        message.value.state = 'success';
        message.value.message = '导入成功';
        const { errorinfo, success, total } = res.data;
        const totalNum = total ? Number(total) : 0;
        const successNum = success ? Number(success) : 0;
        const errorNum = total - success;
        message.value.message = `共计导入数据 ${totalNum} 条，错误[${errorNum}]，成功[${successNum}]`;
        if (errorinfo && Object.keys(errorinfo).length > 0) {
          message.value.rowError = [];
          Object.keys(errorinfo).forEach((key: string) => {
            message.value.rowError.push({
              index: Number(key) + 1,
              info: errorinfo[key].errorInfo,
            });
          });
        }
      } catch (error) {
        message.value.state = 'fail';
        message.value.message = `导入失败！${(error as HttpError).message}`;
      } finally {
        isImporting.value = false;
      }
    };

    // 文件选择变更事件
    const onFileChange = ($event: Event) => {
      const obj = $event.target as IData;
      if (!obj.files) {
        return;
      }
      const selectedFile = obj.files[0];
      obj.value = null; // 置空不然下次文件不变不触发
      uploadFile(selectedFile);
    };

    // 下载模板文件
    const onLinkClick = async () => {
      const res = await ibiz.net.request(props.templateUrl, {
        responseType: 'blob',
      });
      if (res.status === 200) {
        let fileName =
          res.headers['content-disposition']!.split(';')
            .find((str: string) => str.indexOf('filename=') !== -1)
            ?.slice(9) || '';
        fileName = decodeURIComponent(fileName);
        const blob = new Blob([res.data as Blob], {
          type: 'application/vnd.ms-excel',
        });
        const elink = document.createElement('a');
        elink.download = fileName;
        elink.style.display = 'none';
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        URL.revokeObjectURL(elink.href); // 释放URL 对象
        document.body.removeChild(elink);
      }
    };

    const selectFile = () => {
      if (isImporting.value) {
        return;
      }
      inputUpLoad.value.click();
    };

    const onCancelButtonClick = () => {
      emit('close', { ok: false, data: {} });
      props.dismiss?.({ ok: false, data: {} });
    };

    return {
      ns,
      onLinkClick,
      selectFile,
      onCancelButtonClick,
      onFileChange,
      inputUpLoad,
      message,
      isImporting,
    };
  },
  render() {
    return (
      <div class={[this.ns.b()]}>
        <input
          ref='inputUpLoad'
          type='file'
          style='display: none'
          accept='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
          onChange={this.onFileChange}
        />
        <div class={this.ns.e('caption')}>导入数据</div>
        {this.message.state === 'ready' ? (
          <div
            class={[
              this.ns.b('upload'),
              this.ns.is('loading', this.isImporting),
            ]}
            onClick={this.selectFile}
          >
            <img
              class={this.ns.be('upload', 'img')}
              src='./assets/img/icon-import.svg'
            ></img>
            <span class={this.ns.be('upload', 'text')}>单击此区域进行上传</span>
            <div class={this.ns.be('upload', 'loading')}>
              <i-icon type='ios-loading' />
              <span>导入中...</span>
            </div>
          </div>
        ) : (
          <div class={this.ns.b('message')}>
            <div class={this.ns.be('message', 'title')}>导入结果</div>
            <div class={this.ns.be('message', 'content')}>
              {this.message.message}
            </div>
            {this.message.rowError.length > 0 && [
              <div class={this.ns.be('message', 'title')}>错误信息</div>,
              <div class={this.ns.be('message', 'content')}>
                {this.message.rowError.map(item => {
                  return <div>{`第 ${item.index} 行：${item.info}`}</div>;
                })}
              </div>,
            ]}
          </div>
        )}
        <div class={this.ns.e('template-container')}>
          <div class={this.ns.e('template-description')}>
            下载导入模版，并按要求填写：
          </div>
          <div class={this.ns.e('template-link')} onClick={this.onLinkClick}>
            <i-icon type='ios-link' />
            数据导入模板文件
          </div>
        </div>
        <div class={this.ns.e('button-bar')}>
          {this.message.state !== 'ready' && (
            <i-button onClick={this.selectFile}>重新上传</i-button>
          )}
        </div>
      </div>
    );
  },
});
