/*
 * @Author: your name
 * @Date: 2021-06-23 22:29:23
 * @LastEditTime: 2021-06-24 23:54:06
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \Mina_B_T\miniprogram\utils\request.js
 */
/**
 * 这边主要是为公共请求方法服务的 同时支持回调与promise.then两种获取值的方法
 * 我本人喜欢回调方法
 * 如果习惯promise的本方法依旧支持
 */

import { dont_login } from "./config_api";
import { no_openid } from "./config_api";
import { getNetworkType, getDataType, getUrl, getUserId, login } from "./util";
/* 
 请求方法
 @options 请求参数
 @status 是否携带userID
*/
async function formatOption(options: any): Promise<any> {
  /**
   * 检测网络状况 并判断是否发起请求
   * 当无网络时传入 offline 并提示无网络
   */
  const networkType = await getNetworkType();
  if (networkType === 'offline') {
    wx.showToast({
      icon: 'none',
      title: '网络未连接',
    })
    options.success && options.success(networkType)
    return networkType
  }

  /* 拼接接口地址 */
  if (getDataType(options.url) !== 'String') {
    throw new TypeError('接口路径格式错误')
  }

  /*判断是否需要登陆才能调用api */
  options.dont_login = false; //默认全部需要登录
  if (dont_login.length && dont_login.includes(options.url)) {
    options.dont_login = true;
  }

  /**判断是否需要openid才能调用api */
  options.no_openid = false; //默认全部需要
  if (no_openid.length && no_openid.includes(options.url)) {
    options.no_openid = true;
  }

  /* 设置URL */
  options.url = await getUrl(options.url);

  /* 判断是否传入参数 */
  options.data = options.data ? options.data : {};

  /* 设置请求方式并转换为大写*/
  options.method = (options.type ? options.type : 'get').toUpperCase();

  /* 判断是否传入请求头 */
  options.header = options.header || {};

  /* 判断是否传入返回数据格式 */
  options.dataType = options.dataType || 'json';

  /* 判断是否传入响应数据格式 */
  options.responseType = options.responseType || 'text';

  /* 消除空值字段 */
  for (let key in options.data) {
    if (!options.data[key] && options.data[key] !== 0) {
      delete options.data[key]
    }
  }

  /* 根据dont_login判断是否需要登录 */
  if (options.dont_login) {
    return options;
  } else {
    /* 设置userID和usertoken */
    options.data = await getUserId(options.data);
    /** 当user_id与user_token不全时 提示登陆重新获取 */
    console.log('options=>', options);
    if (options.data.user_id && options.data.user_token) {
      return options;
    } else {
      login();
      return false
    }
  }
}

/**
 * @description: 实际执行的请求方法体 执行完之后既能执行回调也能返回promise对象调用
 * @param {any} opt 传入的参数对象
 * @return {*} 返回promise对象
 */
export async function $request<T>(opt: any): Promise<responseOptions<T>> {
  let route = getCurrentPages();
  const options = await formatOption(opt)
  if (options === 'offline') return Promise.reject(options)
  if (!options) return Promise.reject(options);
  return new Promise((resolve, reject) => {
    wx.showLoading({
      mask: true,
      title: '加载中...',
      success: () => {
        console.log('loading start')
      }
    })
    wx.request({
      url: options.url,
      data: options.data,
      header: options.header,
      method: options.method,
      dataType: options.dataType,
      responseType: options.responseType,
      success: function (res) {
        wx.hideLoading({
          success: () => {
            console.log('loding end')
          }
        })
        // 判断是否含有成功方法并执行
        if (res.statusCode === 200) {
          const result: any = res.data
          console.log(result);
          result.errCode = result.errcode
          result.errMsg = result.errmsg
          const errCode = result.errcode || result.errCode;
          if (errCode === 0) {
            options.success && typeof options.success === 'function' && options.success(result);
            resolve(result);
          } else {
            // 判断是否含有失败方法并执行
            if (options.fail && typeof options.fail === 'function') {
              options.fail(result);
              reject(result);
            }
            if (errCode === 2008) {
              login(result.errMsg + ',请重新登录')
              return
            }
            if (errCode === 2009) {
              wx.showToast({
                title: result.errMsg || result.message,
                icon: 'none'
              })
              return
            }
            if (errCode === 2010) {
              login(result.errMsg)
              return
            }

            // model 判断是否自定义模态框或者提示框
            if (!options.model) {
              wx.showModal({
                title: '提示',
                content: result.errMsg || result.message || '网络异常，请检查后重试',
                showCancel: false
              })
            }
          }
        } else {
          options.success && typeof options.success === 'function' && options.success('offline')
          wx.showModal({
            title: '提示',
            content: '网络异常，请检查后重试',
            showCancel: false
          })
        }
      },
      fail: function (res) {
        // 判断是否含有失败方法并执行
        wx.hideLoading({
          success: () => {
            console.log('loading end')
          }
        })
        if (options.fail && typeof options.fail === 'function') {
          options.success && typeof options.success === 'function' && options.success('offline')
          options.fail(res);
          reject(res);
          wx.showModal({
            title: '提示',
            content: '网络异常，请检查后重试',
            showCancel: false
          })
        }
      },
      complete: (res: any) => {
        console.log('请求参数=>', options);
        console.log('请求结果=>', res.data.errmsg, res.data);
        console.log('服务器响应状态=>', res.statusCode);
        console.log('服务器响应结果=>', res);
        console.log('当前页面=>', route[route.length - 1].route);
        console.log(' ');
        wx.stopPullDownRefresh({
          success: () => {
            console.log(route[route.length - 1].route, '=> stopPullDownRefresh')
          }
        });

        // 判断是否含有complete方法并执行
        if (options.complete && typeof options.complete === 'function') {
          options.complete(res.data);
          resolve(res.data);
        }
      },
    })
  })
}
