import extsdk, { baseUtil } from '@hyext/ext-sdk-basic';
import { ERR_WUP_RSP, ERR_WUP_REQ } from '../utils/consts';


export default class WupPretty {
  /**
   * @typedef {Object} WupReq taf请求参数
   * @property {Object} req 请求的jce对象
   * @property {Function} rspClass 响应的jce类
   * @property {string} servant servant/ui
   * @property {string} funcName 方法名
   * @property {number} strategy 策略, 0-加载网络, 2-加载缓存
   * @property {string} reqClassName 请求的jce类名
   * @property {string} rspClassName 响应的jce类名 
   */
  /**
   * @typedef {Object} WupRsp 接口返回数据
   * @property {Object} rsp 返回数据
   * @property {number} [bcode] 返回码
   */
  /**
   * @callback EncoudReq 加密请求
   * @param {WupReq} params 请求数据
   * @returns {Objcet} 返回要发送的数据
   */
  /**
   * @callback SendWupReq 发送Wup消息请求
   * @param {Objcet} params 加密返回的参数
   * @param {Function} RspClass 响应的jce类
   * @returns {string} 返回消息加密串
   */
  /**
   * @callback DecoudRsp 解密请求
   * @param {string} rspStr 请求返回的加密串
   * @param {Function} RspClass 响应的jce类
   * @returns {WupRsp} 返回数据
   */
  /**
   * @typedef {Object} WupPrettyOptions
   * @property {EncoudReq} encoudReq 加密请求
   * @property {Promise<SendWupReq>} sendWupReq 发送Wup消息请求
   * @property {DecoudRsp} decodeRsp 解密请求
   */
  /**
   * @param {WupPrettyOptions} opt 
   */
  constructor(opt) {
    this.opt = Object.assign({}, opt || {});
  }

  /**
   * sendWup 请求
   * @param {WupReq} request 请求参数
   * @param {boolean} unEncode 不需要加密
   * @param {boolean} unDecode 不需要解密
   * @returns {WupRsp} 返回数据
   */
  async sendWup(request) {
    const { encoudReq, decodeRsp, sendWupReq } = this.opt || {};
    const { rspClass, unEncode, unDecode } = request || {};

    let params, rspData;
    try {

      try {
        params = unEncode ? { ...request } : await encoudReq(request);
      } catch (err) {
        // 加密报错
        err.message = err.message || ERR_WUP_REQ.msg
        err.code = err.code || ERR_WUP_REQ.code;
        throw err
      }

      rspData = await sendWupReq(params, rspClass);

      // 不需要解读返回结构
      if (!unDecode && !rspClass) return {};

      try {
        if (unDecode) return rspData
        return await decodeRsp(rspData, rspClass);
      } catch (err) {
        // 解密报错
        err.message = err.message || ERR_WUP_RSP.msg;
        err.code = err.code || ERR_WUP_RSP.code;
        throw err
      }

    } catch (err) {
      const { funcName, servant, reqClassName, rspClassName, req } = request || {};
      const prefix = `sendwup|${funcName}|${servant}|${reqClassName}|${rspClassName}`;
      err.serialize = `${prefix}|${err.serialize || ''}`;
      err.request = request || {};
      err.response = err.response || rspData;
      extsdk.logger.warn(prefix, `\nrequest:`, err.request, `\nrequest.req:`, baseUtil.toStr(req));
      extsdk.logger.warn(prefix, `\nresponse:`, baseUtil.toStr(err.response));

      // 暂时不放到message中
      delete err.request
      delete err.response

      throw err
    }

  }
}

