import BugReporter from "@/common/BugReporter";
import ApiCofig from "@/common/config/ApiCofig";
import AppCofig, { isDev } from "@/common/config/AppCofig";
import { RequestCoreInstance, RequestApiError, UniappImplementer, StringUtils, appendGetUrlParams, appendPostParams, RequestResponse, RequestOptions, type RequestApiInfoStruct, RequestApiResult, type RequestApiErrorType, defaultResponseDataGetErrorInfo, defaultResponseDataHandlerCatch } from "@imengyu/imengyu-utils";
import type { DataModel, KeyValue, NewDataModel } from "@imengyu/js-request-transform";

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

function matchNotReportMessage(code: number, str: string) {
  if (ApiCofig.notReportErrorCode.includes(code))
    return true;
  for (let i = 0; i < ApiCofig.notReportMessages.length; i++) {
    if (ApiCofig.notReportMessages[i].test(str))
      return true;
  }
  return false;
}
//错误报告处理
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.apiRawReq) +
          '\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) {
      BugReporter.reportRequestBug({
        errorType: response.errorType,
        errorMessage: response.errorMessage,
        apiName: response.apiName,
        apiUrl: response.apiUrl,
        rawRequest: response.apiRawReq,
        rawData: response.rawData,
        code: response.code.toString(),
        errorCodeMessage: response.errorCodeMessage,
        data: response.rawData,
      });
    } else  {
      errMsg += '服务出现了异常，请稍后重试或联系客服。';
      errMsg += '版本：' + AppCofig.version;
      uni.showModal({
        title: '抱歉',
        content: errMsg,
        showCancel: false,
      });
      BugReporter.reportError(response);
    }
  }
}

export class BaseAppServerRequestModule<T extends DataModel> extends RequestCoreInstance<T> {
  constructor(baseUrl: string) {
    super(UniappImplementer);
    this.config.baseUrl = baseUrl;
    this.config.errCodes = [];
    //请求拦截器
    this.config.requestInterceptor = (url, req) => {
      //获取app中的token，追加到头;
      const app = getApp();
      if (StringUtils.isNullOrEmpty((req.headers as KeyValue).token as string)) {
        const t = app?.globalData?.token ?? '';
        req.headers['token'] = t
        req.headers['__token__'] = t;
      }
      const main_body_user_id = app?.globalData?.userId ?? '';
      const append_main_body_user_id = !(url.includes('content/content'));

      if (req.method == 'GET') {
        //追加GET参数
        url = appendGetUrlParams(url, 'main_body_id', ApiCofig.mainBodyId);
        //url = appendGetUrlParams(url, 'platform', ApiCofig.platformId);
        if (append_main_body_user_id)
          url = appendGetUrlParams(url, 'main_body_user_id', main_body_user_id);
      } else {
        req.data = appendPostParams(req.data,'main_body_id', ApiCofig.mainBodyId);
        //req.data = appendPostParams(req.data,'platform', ApiCofig.platformId);
        if (append_main_body_user_id)
          req.data = appendPostParams(req.data,'main_body_user_id', main_body_user_id);
      } 
      return { newUrl: url, newReq: req };
    };
    //响应数据处理函数
    this.config.responseDataHandler = async function responseDataHandler<T extends DataModel>(response: RequestResponse, req: RequestOptions, resultModelClass: NewDataModel | undefined, instance: RequestCoreInstance<T>, apiInfo: RequestApiInfoStruct): Promise<RequestApiResult<T>> {
      const method = req.method || 'GET';
      try {
        const json = await response.json();
        if (response.ok) {
          if (!json) {
            throw new RequestApiError(
              'businessError',
              '后端未返回数据',
              '',
              response.status,
              null,
              null,
              response.headers,
              apiInfo
            );
          }

          //code == 0 错误
          if (json.code === 0) {
            throw createError(json);
          }

          //处理后端的数据
          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;
          }
          return new RequestApiResult(
            resultModelClass ?? instance.config.modelClassCreator,
            json?.code || response.status,
            message,
            data,
            json,
            response.headers,
            apiInfo
          );
        }
        else {
          throw createError(json);
        }

        function createError(json: any): RequestApiError {
          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 (StringUtils.isStringAllEnglish(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;
          }

          return new RequestApiError(
            errType,
            errString,
            errCodeStr,
            response.status,
            null,
            null,
            response.headers,
            apiInfo
          );
        }
      } catch (err) {
        if (err instanceof RequestApiError) {
          throw err;
        }
        //错误统一处理
        return new Promise<RequestApiResult<T>>((resolve, reject) => {
          defaultResponseDataHandlerCatch(method, req, response, null, err as any, apiInfo, response.url, reject, instance);
        });
      }
    };
    //错误报告处理
    this.config.responseErrorReportInterceptor = (instance, response) => {
      return (
        (response.errorType !== 'businessError' && response.errorType !== 'networkError') ||
        matchNotReportMessage(response.code, response.errorMessage) === true
      );
    };
    //错误报告处理函数
    this.config.reportError = reportError;
  }
}