
/**
 * 这里写的是业务相关的：
 * * 请求数据处理函数。
 * * 自定义请求模块。
 * * 自定义错误报告处理函数。
 */

import { appendGetUrlParams, appendPostParams, checkIfStringAllEnglish, isNullOrEmpty } from "@/common/request/utils/Utils";
import AppCofig, { isDev } from "../common/config/AppCofig";
import RequestApiConfig from "../common/request/core/RequestApiConfig";
import { RequestApiError, RequestApiResult, type RequestApiErrorType } from "../common/request/core/RequestApiResult";
import { RequestCoreInstance, RequestOptions } from "../common/request/core/RequestCore";
import { defaultResponseDataGetErrorInfo, defaultResponseDataHandlerCatch } from "../common/request/core/RequestHandler";
import type { DataModel, NewDataModel } from "@imengyu/js-request-transform";
import type { KeyValue } from "@/common/utils/CommonUtils";
import { useAuthStore } from "@/store/auth";
import ApiCofig from "@/common/config/ApiCofig";
import uniappImplementer, { Response } from "@/common/request/implementer/Uniapp";

/**
 * 不报告错误的 code
 */
const notReportErrorCode = [401] as number[];
const notReportMessages = [
  /请授权绑定手机号/g,
] as RegExp[];
function matchNotReportMessage(str: string) {
  for (let i = 0; i < notReportMessages.length; i++) {
    if (notReportMessages[i].test(str))
      return true;
  }
  return false;
}

//请求拦截器
function requestInceptor(url: string, req: RequestOptions) {
  //获取store中的token，追加到头;
  const autoStore = useAuthStore();
  if (isNullOrEmpty((req.header as KeyValue).token as string)) {
    req.header['token'] = autoStore.token;
    req.header['__token__'] = autoStore.token;
  }
  if (req.method == 'GET') {
    //追加GET参数
    url = appendGetUrlParams(url, 'main_body_id', ApiCofig.mainBodyId);
  } else {
    req.data = appendPostParams(req.data,'main_body_id', ApiCofig.mainBodyId);
  }
  return { newUrl: url, newReq: req };
}
//响应数据处理函数
function responseDataHandler<T extends DataModel>(response: Response, req: RequestOptions, resultModelClass: NewDataModel|undefined, instance: RequestCoreInstance<T>, apiName: string | undefined): Promise<RequestApiResult<T>> {
  return new Promise<RequestApiResult<T>>((resolve, reject) => {
    const method = req.method || 'GET';
    response.json().then((json) => {
      if (response.ok) {
        if (!json) {
          reject(new RequestApiError(
            'businessError',
            '后端未返回数据',
            '',
            response.status,
            null,
            null,
            req,
            apiName,
            response.url
          ));
          return;
        }

        //code == 0 错误
        if (json.code === 0) {
          handleError();
          return;
        }

        //处理后端的数据
        let message = '未知错误';
        let data = {} as any;

        //后端返回格式不统一，所以在这里处理格式
        if (typeof json.data === 'object') {
          data = json.data;
          message = json.data?.msg || response.statusText;
        }
        else {
          //否则返回上层对象
          data = json;
          message = json.msg || response.statusText;
        }

        resolve(new RequestApiResult(
          resultModelClass ?? instance.config.modelClassCreator,
          json?.code || response.status,
          message,
          data,
          json
        ));
      }
      else {
        handleError();
      }

      function handleError() {
        let errType : RequestApiErrorType = 'unknow';
        let errString = '';
        let errCodeStr = '';

        if (typeof json.message === 'string') 
          errString = json.message;
        if (typeof json.msg === 'string') 
          errString += json.msg;

        if (checkIfStringAllEnglish(errString))
          errString = '服务器返回：' + errString;

        //错误处理
        if (errString) {
          //如果后端有返回错误信息，则收集错误信息并返回
          errType = 'businessError';
          if (typeof json.data === 'object' && json.data?.errmsg) {
            errString += '\n' + json.data.errmsg;
          }
          if (typeof json.errors === 'object') {
            for (const key in json.errors) {
              if (Object.prototype.hasOwnProperty.call(json.errors, key)) {
                errString += '\n' + json.errors[key];
              }
            }
          }
        } else {
          const res = defaultResponseDataGetErrorInfo(response, json);
          errType = res.errType;
          errString = res.errString;
          errCodeStr = res.errCodeStr;
        }

        reject(new RequestApiError(
          errType,
          errString,
          errCodeStr,
          response.status,
          null,
          null,
          req,
          apiName,
          response.url
        ));
      }
    }).catch((err) => {
      //错误统一处理
      defaultResponseDataHandlerCatch(method, req, response, null, err, apiName, response.url, reject, instance);
    });
  });
}
//错误报告处理
function responseErrReoprtInceptor<T extends DataModel>(instance: RequestCoreInstance<T>, response: RequestApiError) {
  return (
    (response.errorType !== 'businessError' && response.errorType !== 'networkError') ||
    notReportErrorCode.indexOf(response.code) >= 0 ||
    matchNotReportMessage(response.errorMessage) === true
  );
}

//错误报告处理
export function reportError<T extends DataModel>(instance: RequestCoreInstance<T>, response: RequestApiError | Error) {
  if (isDev) {
    if (response instanceof RequestApiError) {
      uni.showModal({
        title: `请求错误 ${response.apiName} : ${response.errorMessage}`,
        content: response.toString() +
          '\r\n请求接口：' + response.apiName +
          '\r\n请求地址：' + response.apiUrl +
          '\r\n请求参数：' + JSON.stringify(response.rawRequest) +
          '\r\n返回参数：' + JSON.stringify(response.rawData) +
          '\r\n状态码：' + response.code +
          '\r\n信息：' + response.errorCodeMessage,
        type: 'error',
        showCancel: false,
      });
    } else {
      uni.showModal({
        title: '错误报告 代码错误',
        content: response?.stack || ('' + response),
        type: 'error',
        showCancel: false,
      });
    }
  } else {    
    let errMsg = '';
    if (response instanceof RequestApiError)
      errMsg = response.errorMessage + '。';
      
    errMsg += '服务出现了异常，请稍后重试或联系客服。';
    errMsg += '版本：' + AppCofig.version;

    uni.showModal({
      title: '抱歉',
      content: errMsg,
      showCancel: false,
    });
}
}

/**
 * App服务请求模块
 */
export class AppServerRequestModule<T extends DataModel> extends RequestCoreInstance<T> {
  constructor() {
    super(uniappImplementer);
    this.config.baseUrl = RequestApiConfig.getConfig().BaseUrl;
    this.config.errCodes = []; //
    this.config.requestInceptor = requestInceptor;
    this.config.responseDataHandler = responseDataHandler;
    this.config.responseErrReoprtInceptor = responseErrReoprtInceptor;
    this.config.reportError = reportError;
  }
}
