/**
 * 异常模块
 * @date 2022-03
 * @author 何华东
 */

 import { AxiosError } from "axios";

 /**
  * 参数异常类
  * @param paramName 参数名
  */
 export class ParamError extends Error {
     paramName?: string;
 
     constructor(message: string, paramName?: string) {
         super();
 
         this.name = this.constructor.name;
         this.message = message;
         this.paramName = paramName;
     }
 }
 
 /**
  * 参数无效异常类
  * @param paramName 参数名
  */
 export class ParamInvalidError extends ParamError {
     constructor(paramName?: string) {
         super(`invalid ${paramName || 'param'}.`, paramName);
 
         this.name = this.constructor.name;
     }
 }
 
 /**
  * 参数为空异常类
  * @param paramName 参数名
  */
 export class ParamEmptyError extends ParamError {
     constructor(paramName?: string) {
         super(`${paramName || 'param'} is empty.`, paramName);
 
         this.name = this.constructor.name;
     }
 }
 
 /**
  * 参数解密失败异常类
  * @param paramName 参数名
  */
 export class ParamDecryptFailedError extends ParamError {
     constructor(paramName?: string) {
         super(`${paramName || 'param'} decrypt failed.`, paramName);
 
         this.name = this.constructor.name;
     }
 }
 
 /**
  * 验签失败异常类
  */
 export class ValidateSignFailedError extends Error {
     constructor() {
         super('validate sign failed.');
 
         this.name = this.constructor.name;
     }
 }
 
 /**
  * 接口异常类
  */
 export class ApiError {
     /**
      * 接口分类，例如：统一接口、非标接口、杭停接口，仅为日志记录
      */
     apiCategory: string;
 
     /**
      * 接口描述，例如：2.0.1获取平台配置信息，仅为日志记录
      */
     apiDesc?: string;
 
     /**
      * 错误信息
      */
     message?: string;
 
     /**
      * 请求地址
      */
     requestUrl: string;
 
     /**
      * 请求头
      */
     headers?: any;
 
     /**
      * 请求数据
      */
     data?: any;
 
     /**
      * axiosError.code
      * 
      * ECONNABORTED 为请求超时时
      */
     code?: string;
 
     /**
      * http状态码，例如：200、500、404
      */
     statusCode?: any;
 
     /**
      * 响应
      */
     apiResponse?: any;
 
     toString() {
         return `${this.apiCategory}${this.apiDesc ? this.apiDesc : ''}调用失败,错误信息:${this.message},请求地址:${this.requestUrl},请求头:${JSON.stringify(this.headers)},请求数据:${JSON.stringify(this.data)},HTTP状态码:${this.statusCode},返回值:${JSON.stringify(this.apiResponse)}`;
     }
 }
 
 /**
  * 从axiosError生成一个ApiError异常对象
  */
 function generateApiErrorFromAxiosError(axiosError: AxiosError, apiCategory: string) {
     let apiError = new ApiError();
 
     apiError.apiCategory = apiCategory;
     apiError.apiDesc = axiosError.config['apiDesc'];
     apiError.message = axiosError.message;
     apiError.requestUrl = axiosError.config.url?.startsWith('http') ? axiosError.config.url : (axiosError.config.baseURL + (axiosError.config.url || ''));
     apiError.headers = axiosError.config.headers;
     apiError.data = axiosError.config.data;
     apiError.code = axiosError.code;
     apiError.statusCode = axiosError.response?.status;
     apiError.apiResponse = axiosError.response?.data;
 
     return apiError;
 }
 
 /**
  * 从AxiosError抛出ApiError异常
  * @param apiCategory 接口分类名
  */
 export function throwApiErrorFromAxiosError(axiosError: AxiosError, apiCategory: string) {
     throw generateApiErrorFromAxiosError(axiosError, apiCategory);
 }