/*
 * @Date: 2021-11-27 15:27:19
 * @LastEditors: wanglj
 * @LastEditTime: 2024-03-13 16:34:10
 * @FilePath: \labsop_backup\frontend\packages\base\src\utils\micro_request.js
 * @Description: file content
 */
import { Local, Session } from '@/utils/storage';
import { CACHE_KEY } from '@/constants';

const errorCode = {
  '401': '认证失败，无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误，请反馈给管理员'
};

const baseURL = import.meta.env.VITE_API_URL || '';

function request(options) {
  // 拼接请求路径
  let url = options.url || '';
  if (!/^\/?http/.test(url)) {
    url = baseURL + url;
  }

  // 头部处理
  let header = Object.assign({}, options.headers, options.header);
  header['Content-Type'] = header['Content-Type'] || 'application/json;charset=utf-8';
  
  if (import.meta.env.VITE_TENANT) {
    header['Tenant'] = import.meta.env.VITE_TENANT;
  }

  // 是否需要设置 token
  const isToken = header.isToken === false;
  const token = Local.get(CACHE_KEY.TOKEN);
  if (token && !isToken) {
    header['Authorization'] = 'Bearer ' + token;
  }

  // uni.request 只有在 Content-Type 为 application/json 时才自动对对象执行 JSON.stringify
  // 对于 application/rpcx，需要手动序列化，否则会被 toString() 处理成 [object Object]
  let requestData = options.data;
  if (typeof requestData === 'object' && requestData !== null && header['Content-Type'] === 'application/rpcx') {
    requestData = JSON.stringify(requestData);
  }

  return new Promise((resolve, reject) => {
    uni.request({
      url: url,
      method: (options.method || 'GET').toUpperCase(),
      data: requestData,
      header: header,
      timeout: options.timeout || 60000,
      responseType: options.responseType || 'text',
      success: (res) => {
        // 文件流处理
        if (options.responseType === 'arraybuffer' || res.header?.['content-type']?.includes('application/octet-stream')) {
          downLoadBlobFile(res, options);
          resolve(res.data);
          return;
        }
        processResponse(res, resolve, reject);
      },
      fail: (err) => {
        console.log('err: ', err);
        uni.showToast({
          title: err.errMsg || '网络环境异常，请稍后重试',
          icon: 'none',
          duration: 3000
        });
        reject(err);
      }
    });
  });
}

function processResponse(res, resolve, reject) {
  const data = res.data || {};
  // 未设置状态码则默认成功状态
  const code = data.code || res.statusCode || 200;
  // 获取错误信息
  const message = errorCode[code] || data.message || data.msg || errorCode['default'];

  if (code === 401) {
    uni.showModal({
      title: '系统提示',
      content: '登录状态已过期，您可以继续留在该页面，或者重新登录',
      confirmText: '重新登录',
      cancelText: '取消',
      success: function (modalRes) {
        if (modalRes.confirm) {
          // 清除缓存/token等
          Session.clear();
          Local.remove(CACHE_KEY.TOKEN);
          // 重新定向到登录页
          uni.reLaunch({
            url: '/pages/login/index'
          });
        }
      }
    });
    reject(new Error(message));
  } else if (code === 500) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    });
    reject(new Error(message));
  } else if (code !== 200) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    });
    reject(new Error(message));
  } else {
    // 返回真实的业务数据，此处直接返回 data（也可根据业务需要只回 data.data）
    resolve(data);
  }
}

function downLoadBlobFile(res, options) {
  let mimeType = options.mimeType || 'application/vnd.ms-excel';
  let fileName = 'data.xlsx';

  // 尝试从header中获取文件名
  const header = res.header || {};
  let contentDisposition = header['content-disposition'] || header['Content-Disposition'];
  if (contentDisposition) {
    let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*');
    let result = patt.exec(decodeURI(contentDisposition));
    if (result && result.length > 1) {
      fileName = result[1];
      fileName = decodeURI(escape(fileName));
      fileName = fileName.replace(/\"/g, '');
    }
  }

  // #ifdef H5
  const blob = new Blob([res.data], { type: mimeType });
  const aLink = document.createElement('a');
  aLink.href = URL.createObjectURL(blob);
  aLink.setAttribute('download', fileName);
  document.body.appendChild(aLink);
  aLink.click();
  document.body.removeChild(aLink);
  // #endif

  // #ifndef H5
  // 非H5平台（小程序、APP等）需要使用原生的文件保存及打开API
  const fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null;
  if (fs && res.data) {
    const filePath = `${uni.env.USER_DATA_PATH}/${fileName}`;
    fs.writeFile({
      filePath: filePath,
      data: res.data,
      encoding: 'binary',
      success: () => {
        uni.openDocument({
          filePath: filePath,
          showMenu: true,
          success: function () {
            console.log('打开文档成功');
          }
        });
      },
      fail: (err) => {
        uni.showToast({ title: '保存文件失败', icon: 'none' });
      }
    });
  } else {
    uni.showToast({
      title: '文件已下载，但当前平台暂不支持直接打开',
      icon: 'none',
      duration: 3000
    });
  }
  // #endif
}

request.postRequest = function postRequest(basePath, srvName, funcName, data) {
  if (data == undefined) {
    data = { nullparam: 0 };
  }

  return request({
    url: basePath,
    method: 'post',
    headers: {
      'Content-Type': 'application/rpcx',
      'X-RPCX-SerializeType': '1',
      'X-RPCX-ServicePath': srvName,
      'X-RPCX-ServiceMethod': funcName,
      Srvenv: 'dev',
    },
    data: data,
  });
};

// 发出请求并要求把客户端信息传输给后端（IP和User-Agent）
request.postRequestWithClientInfo = function postRequestWithClientInfo(basePath, srvName, funcName, data) {
  if (data == undefined) {
    data = { nullparam: 0 };
  }
  return request({
    url: basePath,
    method: 'post',
    headers: {
      'Content-Type': 'application/rpcx',
      'X-RPCX-SerializeType': '1',
      'X-RPCX-ServicePath': srvName,
      'X-RPCX-Meta': 'need_clint_Info=1',
      Srvenv: import.meta.env.VITE_SRV_ENV || 'dev',
    },
    data: data,
  });
};

// Excel文件下载（服务端生成文件流）
request.downloadExcel = function downloadExcel(basePath, srvName, funcName, data) {
  if (data == undefined) {
    data = { nullparam: 0 };
  }
  
  let base_Path = '';
  // 使用 import.meta.env 替换 process.env
  if (basePath == import.meta.env.VITE_APP_FOSHAN_PATH) {
    base_Path = (import.meta.env.VITE_APP_MicroSrvProxy_foshan_API || '') + basePath;
  } else if (basePath == import.meta.env.VITE_APP_AdminPath) {
    base_Path = (import.meta.env.VITE_APP_MicroSrvProxy_API || '') + basePath;
  } else {
    base_Path = basePath;
  }

  return request({
    url: base_Path,
    method: 'post',
    responseType: 'arraybuffer', // uniapp中使用 arraybuffer 替代 blob下载文件
    headers: {
      'Content-Type': 'application/rpcx',
      'X-RPCX-SerializeType': '1',
      'X-RPCX-ServicePath': srvName,
      'X-RPCX-ServiceMethod': funcName,
      Srvenv: 'dev',
    },
    data: data,
  });
};

export default request;
