import { onBeforeUnmount } from 'vue';
import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import type { MessageReactive } from 'naive-ui';
import type { MessageApiInjection } from 'naive-ui/es/message/src/MessageProvider';
import { useLoading } from '@sa/hooks';
import { getAuthorization } from '@/service/request/shared';

interface MimeMap {
  xlsx: string;
  zip: string;
  oss: string;
}

const mimeMap: MimeMap = {
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  zip: 'application/zip',
  oss: 'application/octet-stream'
};

const baseUrl = import.meta.env.VITE_SERVICE_BASE_URL;

export function useDownLoadFile() {
  let messageReactive: MessageReactive | undefined | null;
  const { loading, startLoading, endLoading } = useLoading();

  function paramsGetToUrl(url: string, params: Record<string, any> | null): string {
    let urlparams = url;
    if (params) {
      urlparams = `${url}?`;
      for (const propName of Object.keys(params)) {
        const value = params[propName];
        const part = `${encodeURIComponent(propName)}=`;
        if (value !== null && typeof value !== 'undefined') {
          if (typeof value === 'object') {
            // eslint-disable-next-line max-depth
            for (const key of Object.keys(value)) {
              // eslint-disable-next-line max-depth
              if (value[key] !== null && typeof value[key] !== 'undefined') {
                const par = `${propName}[${key}]`;
                const subPart = `${encodeURIComponent(par)}=`;
                urlparams += `${subPart + encodeURIComponent(value[key])}&`;
              }
            }
          } else {
            urlparams += `${part + encodeURIComponent(value)}&`;
          }
        }
      }
      urlparams = urlparams.slice(0, -1);
    }
    return baseUrl + urlparams;
  }

  function getPostParams(params: Record<string, any> | null) {
    const dataParams: Record<string, any> = {}; // 用于存放请求体数据
    // get请求映射params参数
    if (params) {
      for (const propName of Object.keys(params)) {
        const value = params[propName];
        if (value !== null && typeof value !== 'undefined') {
          if (typeof value === 'object') {
            // eslint-disable-next-line max-depth
            for (const key of Object.keys(value)) {
              // eslint-disable-next-line max-depth
              if (value[key] !== null && typeof value[key] !== 'undefined') {
                const nestedKey = `${propName}[${key}]`;
                dataParams[nestedKey] = value[key];
              }
            }
          } else {
            dataParams[propName] = value;
          }
        }
      }
    }
    return dataParams;
  }

  function handleRequest(config: AxiosRequestConfig, mine: keyof MimeMap, filename: string) {
    createMessage('warning', '正在导出中，请稍后...');

    axios(config)
      .then(res => {
        resolveBlob(res, mine, filename);
      })
      .catch(err => {
        createMessage('error', err.message);
        endLoading();
      });
  }

  function downLoadOss(ossId: string | number = '', filename: string = '') {
    handleRequest(
      {
        method: 'get',
        url: `${baseUrl}/system/oss/download/${ossId}`,
        responseType: 'blob',
        headers: { Authorization: getAuthorization() }
      },
      'oss',
      filename
    );
  }

  function downLoadZip(url: string, filename: string = '') {
    handleRequest(
      {
        method: 'get',
        url: baseUrl + url,
        responseType: 'blob',
        headers: { Authorization: getAuthorization() }
      },
      'zip',
      filename
    );
  }

  function downLoadZipPost(url: string, params: Record<string, any> | null = null, filename: string = '') {
    handleRequest(
      {
        method: 'post',
        url: baseUrl + url,
        data: getPostParams(params),
        responseType: 'blob',
        headers: {
          Authorization: getAuthorization(),
          'Content-Type': 'application/json;charset=utf-8' // 设置请求体类型
        }
      },
      'zip',
      filename
    );
  }

  function downLoadExcel(url: string, params: Record<string, any> | null = null, filename: string = '') {
    handleRequest(
      {
        method: 'get',
        url: paramsGetToUrl(url, params),
        responseType: 'blob',
        headers: {
          Authorization: getAuthorization()
        }
      },
      'xlsx',
      filename
    );
  }

  function downLoadExcelPost(url: string, params: Record<string, any> | null = null, filename: string = '') {
    handleRequest(
      {
        method: 'post',
        url: baseUrl + url,
        data: getPostParams(params),
        responseType: 'blob',
        headers: {
          Authorization: getAuthorization(),
          'Content-Type': 'application/json;charset=utf-8' // 设置请求体类型
        }
      },
      'xlsx',
      filename
    );
  }

  function resolveBlob(res: AxiosResponse, mime: keyof MimeMap, filename: string) {
    const mimeType = mimeMap[mime];
    if (res.headers['content-type'].includes('application/json')) {
      const fileReader = new FileReader();
      fileReader.readAsText(new Blob([res.data], { type: 'application/octet-stream' }), 'utf-8');
      fileReader.onload = () => {
        try {
          const result = JSON.parse(fileReader.result as string);
          if (result.code === 500) {
            removeMessage();
            messageReactive = window.$message?.error(`导出失败：${result.msg}`, { duration: 0 });
          }
        } catch {
          removeMessage();
          messageReactive = window.$message?.error(`系统错误,请联系管理员`, { duration: 0 });
        }
      };
      endLoading();
      setTimeout(() => {
        removeMessage();
      }, 3000);
      return;
    }

    const aLink = document.createElement('a');
    const blob = new Blob([res.data], { type: mimeType });
    // //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
    const patt = /filename=([^;]+\.[^.;]+);*/;
    const contentDisposition = decodeURI(res.headers['content-disposition']);
    const result = patt.exec(contentDisposition);
    // var fileName = result[1]
    // fileName = fileName.replace(/\"/g, '')
    let fileName: string | undefined = '';
    if (filename) {
      fileName = filename;
    } else {
      fileName = result?.[1];
      fileName = fileName?.replace(/"/g, '');
    }
    aLink.style.display = 'none';
    aLink.href = URL.createObjectURL(blob);
    aLink.setAttribute('download', decodeURI(typeof fileName === 'string' ? fileName : '')); // 设置下载文件名称
    document.body.appendChild(aLink);
    aLink.click();
    URL.revokeObjectURL(aLink.href); // 清除引用
    document.body.removeChild(aLink);

    createMessage('success', '导出成功');
    endLoading();
    setTimeout(() => {
      removeMessage();
    }, 3000);
  }

  // 创建消息框
  function createMessage(type: keyof MessageApiInjection, message: string) {
    startLoading();
    removeMessage();
    messageReactive = window.$message?.[type](message, { duration: 0 }) as MessageReactive;
  }

  // 移出消息框
  function removeMessage() {
    if (messageReactive) {
      messageReactive.destroy();
      messageReactive = null;
    }
  }

  onBeforeUnmount(() => {
    removeMessage();
  });

  return {
    loading,
    downLoadOss,
    downLoadZip,
    downLoadZipPost,
    downLoadExcel,
    downLoadExcelPost
  };
}
