import { UploadEditorController } from '@ibiz-template/controller';
import { defineComponent, onMounted, ref, watch } from 'vue';
import type { PropType } from 'vue';
import { useNamespace } from '@ibiz-template/vue-util';
import { getCookie } from 'qx-util';
import '@/styles/components/editor/app-image-upload/app-image-upload.scss';

export default defineComponent({
  props: {
    value: String,
    controller: {
      type: UploadEditorController,
      required: true,
    },
    data: {
      type: Object as PropType<IData>,
      required: true,
    },
  },
  emits: {
    change: (_value: string | null) => true,
  },
  setup(props, { emit }) {
    const ns = useNamespace('app-image-upload');

    const c = props.controller;

    // 文件列表
    const files = ref<IData[]>([]);

    // 请求头
    const headers = ref<IData>({});

    // 上传文件路径
    const uploadUrl = ref<string>(ibiz.env.baseUrl + ibiz.env.UploadFile);

    // 下载文件路径
    const downloadUrl = ref<string>(ibiz.env.baseUrl + ibiz.env.ExportFile);

    // 设置files
    const setFiles = (value: string | null | undefined) => {
      if (value === null) {
        files.value = [];
      }
      if (!value) {
        return;
      }
      const _files = JSON.parse(value);
      if (
        value &&
        Object.prototype.toString.call(_files) === '[object Array]'
      ) {
        files.value = _files;
      } else {
        files.value = [];
      }
    };

    // 文件上传缓存对象
    const uploadCache: IData = {
      count: 0,
      cacheFiles: [],
    };

    // 处理参数
    const dataProcess = () => {
      let _url = ibiz.env.baseUrl + ibiz.env.UploadFile;
      if (c.upload_params.length > 0) {
        _url += '?';
        c.upload_params.forEach((item: IData, i: number) => {
          _url += `${Object.keys(item)[0]}=${Object.values(item)[0]}`;
          if (i < c.upload_params.length - 1) {
            _url += '&';
          }
        });
      }
      uploadUrl.value = _url;

      files.value.forEach((file: IData) => {
        let url = `${downloadUrl.value}/${file.id}`;
        if (c.export_params.length > 0) {
          url += '?';
          c.export_params.forEach((item: IData, i: number) => {
            url += `${Object.keys(item)[0]}=${Object.values(item)[0]}`;
            if (i < c.export_params.length - 1) {
              url += '&';
            }
          });
        }
        // eslint-disable-next-line no-param-reassign
        file.url = url;
      });
    };

    // 设置头
    const setHeaders = () => {
      if (getCookie('access_token')) {
        headers.value.Authorization = `Bearer ${getCookie('access_token')}`;
      }
    };
    setHeaders();

    watch(
      () => props.value,
      newVal => {
        setFiles(newVal);
        dataProcess();
      },
      { immediate: true },
    );

    watch(
      () => props.data,
      newVal => {
        c.getParams(newVal);
      },
      { immediate: true, deep: true },
    );

    onMounted(() => {
      c.getParams(props.data);
      setFiles(props.value);
      dataProcess();
    });

    // 上传前回调
    const beforeUpload = () => {
      uploadCache.count += 1;
    };

    // 上传成功回调
    const onSuccess = (response: IData) => {
      if (!response) {
        return;
      }

      // 处理回调数据，并缓存
      const arr: IData[] = [];
      if (response?.length > 0) {
        for (let index = 0; index < response.length; index++) {
          const file = response[index];
          arr.push({ name: file.filename, id: file.fileid });
        }
      } else {
        arr.push({ name: response.filename, id: response.fileid });
      }
      uploadCache.cacheFiles.push(arr);
      uploadCache.count -= 1;

      // 回调都结束后的处理
      if (uploadCache.count === 0) {
        const result: IData[] = [];
        // 添加已有的文件数据
        files.value.forEach((_file: IData) => {
          result.push({ name: _file.name, id: _file.id });
        });

        // 添加缓存的文件数据
        uploadCache.cacheFiles.forEach((item: IData[]) => {
          result.push(...item);
        });

        // 抛出值变更事件
        const value: string | null =
          result.length > 0 ? JSON.stringify(result) : null;
        emit('change', value);
        // 清空缓存的文件数据
        uploadCache.cacheFiles = [];
      }
    };

    // 上传失败回调
    const onError = (error: IData) => {
      uploadCache.count -= 1;
      console.log(error);
    };

    // 删除回调
    const onRemove = (file: IData, fileList: IData[]) => {
      const arr: Array<IData> = [];
      fileList.forEach((f: IData) => {
        if (f.id !== file.id) {
          arr.push({ name: f.name, id: f.id });
        }
      });
      const value: string | null = arr.length > 0 ? JSON.stringify(arr) : null;
      emit('change', value);
    };

    // 计算文件mime类型
    const calcFilemime = (filetype: string) => {
      let mime = 'image/png';
      switch (filetype) {
        case '.wps':
          mime = 'application/kswps';
          break;
        case '.doc':
          mime = 'application/msword';
          break;
        case '.docx':
          mime =
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
          break;
        case '.txt':
          mime = 'text/plain';
          break;
        case '.zip':
          mime = 'application/zip';
          break;
        case '.png':
          mime = 'image/png';
          break;
        case '.gif':
          mime = 'image/gif';
          break;
        case '.jpeg':
          mime = 'image/jpeg';
          break;
        case '.jpg':
          mime = 'image/jpeg';
          break;
        case '.rtf':
          mime = 'application/rtf';
          break;
        case '.avi':
          mime = 'video/x-msvideo';
          break;
        case '.gz':
          mime = 'application/x-gzip';
          break;
        case '.tar':
          mime = 'application/x-tar';
          break;
        default:
          mime = 'image/png';
      }
      return mime;
    };

    /**
     * 下载文件
     */
    const DownloadFile = (url: string, file: IData) => {
      let tempDownloadUrl: string = url;
      const BaseUrl = ibiz.env.baseUrl;
      if (url.startsWith(BaseUrl)) {
        tempDownloadUrl = url.replace(BaseUrl, '');
      }
      // 发送get请求
      ibiz.net
        .get(
          tempDownloadUrl,
          {},
          {},
          {
            responseType: 'blob',
          },
        )
        .then((response: IData) => {
          if (!response || response.status !== 200) {
            console.log('error');
            return;
          }
          // 请求成功，后台返回的是一个文件流
          if (response.data) {
            // 获取文件名
            const filename = file.name;
            const ext = `.${filename.split('.').pop()}`;
            const filetype = calcFilemime(ext);
            // 用blob对象获取文件流
            const blob = new Blob([response.data], { type: filetype });
            // 通过文件流创建下载链接
            const href = URL.createObjectURL(blob);
            // 创建一个a元素并设置相关属性
            const a = document.createElement('a');
            a.href = href;
            a.download = filename;
            // 添加a元素到当前网页
            document.body.appendChild(a);
            // 触发a元素的点击事件，实现下载
            a.click();
            // 从当前网页移除a元素
            document.body.removeChild(a);
            // 释放blob对象
            URL.revokeObjectURL(href);
          } else {
            console.log('error');
          }
        })
        .catch(error => {
          console.error(error);
        });
    };

    // 下载文件
    const onDownload = (file: IData) => {
      const url = file.url;
      DownloadFile(url, file);
    };

    const dialogImageUrl = ref<string>('');
    const dialogVisible = ref<boolean>(false);

    const onDialogVisibleChange = (value: boolean) => {
      dialogVisible.value = value;
    };

    // 预览
    const onPreview = (file: IData) => {
      dialogImageUrl.value = file.url;
      dialogVisible.value = true;
    };

    return {
      ns,
      c,
      files,
      headers,
      uploadUrl,
      dialogImageUrl,
      dialogVisible,
      beforeUpload,
      onSuccess,
      onError,
      onRemove,
      onDownload,
      onDialogVisibleChange,
      onPreview,
    };
  },
  render(h) {
    return (
      <div class={this.ns.b()}>
        <div class={this.ns.e('image-upload-list')}>
          {this.files.map(item => (
            <div key={item.id} class={this.ns.e('list-item')}>
              <img src={item.url} />
              <div class={this.ns.e('list-item-cover')}>
                <i-icon
                  type='ios-eye-outline'
                  on-click={() => this.onPreview(item)}
                ></i-icon>
                <i-icon
                  type='ios-download-outline'
                  on-click={() => this.onDownload(item)}
                ></i-icon>
                <i-icon
                  type='ios-trash-outline'
                  on-click={() => this.onRemove(item, this.files)}
                ></i-icon>
              </div>
            </div>
          ))}
        </div>

        {h(
          'IUpload',
          {
            ref: 'imageUpload',
            props: {
              action: this.uploadUrl,
              headers: this.headers,
              'default-file-list': this.files,
              multiple: this.c.multiple,
              type: 'drag',
              accept: this.c.accept,
              'show-upload-list': false,
              'before-upload': this.beforeUpload,
              'on-success': this.onSuccess,
              'on-error': this.onError,
              'on-remove': this.onRemove,
              'on-preview': this.onDownload,
            },
          },
          [
            <div class={this.ns.e('btn')}>
              <i-icon type='ios-add' size='30'></i-icon>
            </div>,
          ],
        )}

        <i-modal
          class-name={this.ns.b('upload-model')}
          footer-hide={true}
          value={this.dialogVisible}
          on-on-visible-change={this.onDialogVisibleChange}
        >
          <img
            class={this.ns.be('upload-model', 'model-img')}
            src={this.dialogImageUrl}
          />
        </i-modal>
      </div>
    );
  },
});
