const system = require("../../system");
const settings = require("../../../config/settings");
const md5 = require("md5");
const moment = require("moment");
const axios = require("axios");
const uuidv1 = require('uuid/v1');

class BpoSDPJApi {
  constructor() {

    this.cwxsignapiSve = system.getObject("service.cwxsignapiSve");
    this.redisClient = system.getObject("util.redisClient");

    this.cwxsigninfoSve = system.getObject("service.cwxsigninfoSve");

    this.utilesignbaoSve = system.getObject("service.utilesignbaoSve");

    this.ecompanySve = system.getObject("service.ecompanySve");
    this.etemplateSve = system.getObject("service.etemplateSve");
    this.econtractSve = system.getObject("service.econtractSve");

    this.dkcompanySve = system.getObject("service.dkcompanySve");
    this.dktemplateSve = system.getObject("service.dktemplateSve");
    this.dkcontractSve = system.getObject("service.dkcontractSve");

    this.EXCEPT_KEYS = ['sign'];

    this.ccashinfoSve = system.getObject("service.ccashinfoSve");
    this.ccashuserSve = system.getObject("service.ccashuserSve");
    this.ecompanybusiDao = system.getObject("db.ecompanybusiDao");
    this.qrClient = system.getObject("util.qrClient");
    this.idcardClient = system.getObject("util.idcardClient");
    this.esettleSve = system.getObject("service.esettleSve");

    this.ecompanybusiSve = system.getObject("service.ecompanybusiSve");

    this.redisLock = system.getObject("util.redisLock");
    this.bankthreelogSve = system.getObject("service.bankthreelogSve");
    this.etemplateSve = system.getObject("service.etemplateSve");


    this.dictionary = system.getObject("util.dictionary");

    this.resultMap = {
      0: "操作成功",
      1: "操作失败",
      1001001: "签名失败",
      1002001: "参数错误",
      500: "接口异常",
    }
  }

  trim(o) {
    if (!o) {
      return "";
    }
    return o.toString().trim();
  }

  // async testqr(obj, req) {
  //   let arr = [];
  //   for (let i = 0; i < 20; i++) {
  //     this.tttttt();
  //     // let url = await this.qrClient.generateQR("https://bpohhr.gongsibao.com/sdpj?no=D6L0EoGg1wkzO5GEvm%2B9hA%3D%3D&outTradeNo=01234567891011121319&mchtId=1286935856342376450");
  //     // arr.push(url);
  //   }
  //   return arr;
  // }
  //
  // async tttttt() {
  //   let url = await this.qrClient.generateQR("https://bpohhr.gongsibao.com/sdpj?no=D6L0EoGg1wkzO5GEvm%2B9hA%3D%3D&outTradeNo=01234567891011121319&mchtId=1286935856342376450");
  //   console.log(url);
  // }
  async testWxResult() {
    let arr = ["NAME_MISMATCH:真实姓名不一致.", "NO_AUTH:此请求可能存在风险，已被微信拦截。", "NO_AUTH:用户账号被冻结，无法付款", "SENDNUM_LIMIT:该用户今日付款次数超过限制,如有需要请进入微信支付商户平台-产品中心-企业付款到零钱-产品设置进行修改", "SUCCESS:支付失败", "V2_ACCOUNT_SIMPLE_BAN:非实名用户账号不可发放", "交易成功", "商户下有用户未签约", "商户订单号已存在", "女性年龄必须在18到55之间", "报文请求异常", "报文请求异常A1290188506905247745", "报文请求异常A1290463471281963010", "报文请求异常B1290188503959044098", "提现申请成功", "无法给未实名用户付款", "未开通此账户类型发薪", "男性年龄必须在18到60之间", "系统内部错误", "账户余额不足DSL", "银行客户端异常", "领取失败",];

    for (let a of arr) {
      console.log(this.getWxResult(a));
    }
  }

  async sdpjCronTask() {
    let ids = await this.ccashinfoSve.findUnNotifyIds();
    console.log("------推送数据------", ids);
    if (!ids || ids.length != 0) {
      for (let obj of ids) {
        await this.notifyCash(obj.id);
      }
    }
    console.log("------推送数据------", ids);
    return ids;
  }

  /**
   * 生成二维码
   * @param obj
   * @param req
   * @returns {Promise<{msg: string, code: number}>}
   */
  async cashQRCode(obj, req) {
    // 检验所有参数是否完整 如果出现非法参数直接返回
    if (!obj.appId) {
      return this.getBaseResult(1002001, "appId不存在");
    }
    if (!obj.mchtId) {
      return this.getBaseResult(1002001, "mchtId不存在");
    }
    if (!obj.outTradeNo) {
      return this.getBaseResult(1002001, "商户订单号[outTradeNo]不存在");
    }
    if (!obj.notifyUrl) {
      return this.getBaseResult(1002001, "商户订单号[notifyUrl]不存在");
    }
    let otnLen = this.trim(obj.outTradeNo).length;
    if (otnLen < 10 || otnLen > 32) {
      return this.getBaseResult(1002001, "商户订单号[outTradeNo]长度10-32");
    }

    if (!obj.amt) {
      return this.getBaseResult(1002001, "请设置申请金额");
    }
    if (!obj.ecid) {
      return this.getBaseResult(1002001, "ecid不存在");
    }

    // 获取api信息
    let api = await this.ecompanybusiSve.findOne({
      appId: obj.appId,
      etemplate_id: obj.ecid,
      mchtId: obj.mchtId,
    });
    if (!api) {
      return this.getBaseResult(1001003, "配置信息错误，请联系薪必果人员进行配置");
    }

    // 签名验证
    let param = {
      appId: obj.appId,
      ecid: obj.ecid,
      mchtId: obj.mchtId,
      amt: obj.amt,
      idName: obj.idName,
      idNo: obj.idNo,
      outTradeNo: obj.outTradeNo,
      nonceStr: obj.nonceStr,
      notifyUrl: obj.notifyUrl,
    };
    let sign = system.getSign(param, api.key, this.EXCEPT_KEYS);
    if (sign != obj.sign) {
      return this.getBaseResult(1001001, "签名失败");
    }

    try {
      // mchtId & ecid 进行联合查询 如果存在直接返回
      let _cCashInfo = await this.ccashinfoSve.findOne({
        app_id: obj.appId,
        mchtId: obj.mchtId,
        outTradeNo: obj.outTradeNo,
      }) || {};

      console.log(`bpoSDPJApi.js -> cashQRCode -> mchtId & ecid 进行联合查询 :参数=` + JSON.stringify(obj) + "  _cCashInfo = " + JSON.stringify(_cCashInfo));
      //如果二维码有效直接返回
      if (_cCashInfo.qrcode_status == 1 && _cCashInfo.qrcode) {
        return this.getCodeResult(0, {"qrcode": _cCashInfo.qrcode});
      }

      if (!_cCashInfo.id) {
        _cCashInfo.app_type = api.app_type;
        _cCashInfo.outTradeNo = obj.outTradeNo;
        _cCashInfo.mchtId = obj.mchtId;
        _cCashInfo.ecid = api.etemplate_id;
        _cCashInfo.app_id = obj.appId;
        _cCashInfo.amt = Number(obj.amt || 0);
        _cCashInfo.idName = this.trim(obj.idName) || "";
        _cCashInfo.idNo = this.trim(obj.idNo) || "";
        _cCashInfo.notify_url = this.trim(obj.notifyUrl) || "";
        // 保存签约数据
        _cCashInfo = await this.ccashinfoSve.create(_cCashInfo);
      }

      // 拼接h5 http连接 http//xxx?mchtId=xxx&ecid=xxx&no=id
      let _no = await this.setNo(_cCashInfo.id.toString());
      _no = encodeURIComponent(_no);
      let custormUrl = `https://bpohhr.gongsibao.com/sdpj?no=${_no}&outTradeNo=${_cCashInfo.outTradeNo}&mchtId=${_cCashInfo.mchtId}`;
      console.log("----------------->" + custormUrl);
      // 生成二维码
      let url = await this.qrClient.generateQR(custormUrl);
      _cCashInfo.qrcode = url;
      _cCashInfo.qrcode_status = 1;
      _cCashInfo.sign_url = custormUrl;
      _cCashInfo.save();
      return this.getCodeResult(0, {"qrcode": url || ""});
    } catch (e) {
      let result = {
        code: 500,
        msg: "接口异常"
      };
      console.log(e.stack);
      return result;
    }
  }

  setNo(no) {
    return system.encryption(no);
  }

  async setNoTest(params) {
    return system.encryption(params.no);
  }

  getNo(no) {
    return system.decryption(no);
  }

  getWxResult(msg) {
    console.log("------------------wxResult-msg0----------------", msg);
    if(!msg) {
      return "";
    }

    let map = this.dictionary.getDic("WX_RESULT_MAP") || {};
    for (let k in map) {
      let v = map[k];
      if (msg.indexOf(k) != -1) {
        console.log("------------------wxResult-msg-return1----------------", v);
        return v;
      }
    }

    if (msg.indexOf("NO_AUTH") != -1) {
      msg = msg.replace("NO_AUTH:", "");
      msg = msg.replace("NO_AUTH", "");
    }
    console.log("------------------wxResult-msg-return2----------------", msg);
    return msg;
  }

  async qrcodeDesc(obj, req) {
    try {
      let params = {
        appId: obj.appId,
        mchtId: obj.mchtId,
        ecid: obj.ecid,
        outTradeNo: obj.outTradeNo,
        nonceStr: obj.nonceStr,
        sign: obj.sign,
      };

      let api = await this.ecompanybusiSve.findOne({
        appId: obj.appId,
        etemplate_id: obj.ecid,
        mchtId: obj.mchtId,
      });
      if (!api) {
        return this.getBaseResult(1001003, "配置信息错误，请联系薪必果人员进行配置");
      }
      let sign = system.getSign(params, api.key, this.EXCEPT_KEYS);
      if (obj.sign != sign) {
        return this.getBaseResult(1001001, "签名失败");
      }

      let cashInfo = await this.ccashinfoSve.findOne({
        mchtId: params.mchtId,
        outTradeNo: params.outTradeNo,
      });
      if (!cashInfo) {
        return this.getErrResult("二维码不存在");
      }

      let statusName;
      if (cashInfo.qrcode_status == 2) {
        statusName = "已失效";
      } else if (!cashInfo.trade_status) {
        statusName = "待领取";
      } else if (cashInfo.trade_status == "00") {
        statusName = "已领取";
      } else if (cashInfo.trade_status == "01") {
        statusName = "领取中";
      } else if (cashInfo.trade_status == "02") {
        statusName = "领取失败";
      } else {
        statusName = "状态错误";
      }
      let dto = {
        appId: cashInfo.app_id,
        mchtId: cashInfo.mchtId,
        outTradeNo: cashInfo.outTradeNo || "",
        qrcodeStatus: cashInfo.qrcode_status || "",
        tradeStatus: cashInfo.trade_status || "",
        tradeDesc: cashInfo.trade_desc,
        statusName: statusName,
        idName: cashInfo.id_name,
        idNo: cashInfo.id_no,
        openId: cashInfo.openId,
        nonceStr: await this.getUidStr(32, 36)
      };
      dto.sign = system.getSign(dto, api.key, this.EXCEPT_KEYS);
      return this.getSuccessResult("SUCCESS", dto);
    } catch (e) {
      console.log(e);
      return this.getBaseResult(500, "接口异常");
    }
    return this.getSuccessResult();
  }

  /**
   * 二维码作废
   * @param obj
   * @param req
   * @returns {Promise<{msg: string, code: number, data: {}}>}
   */
  async removeQRCode(obj, req) {
    try {
      console.log("----removeqrcode----", obj.outTradeNo, new Date());
      let params = {
        appId: obj.appId,
        mchtId: obj.mchtId,
        ecid: obj.ecid,
        outTradeNo: obj.outTradeNo,
        nonceStr: obj.nonceStr,
        sign: obj.sign,
      };

      let api = await this.ecompanybusiSve.findOne({
        appId: obj.appId,
        etemplate_id: obj.ecid,
        mchtId: obj.mchtId,
      });
      if (!api) {
        return this.getBaseResult(1001003, "配置信息错误，请联系薪必果人员进行配置");
      }

      let sign = system.getSign(params, api.key, this.EXCEPT_KEYS);
      if (obj.sign != sign) {
        return this.getBaseResult(1001001, "签名失败");
      }

      let cashInfo = await this.ccashinfoSve.findOne({
        mchtId: params.mchtId,
        outTradeNo: params.outTradeNo,
      });

      if (!cashInfo) {
        return this.getErrResult("二维码不存在");
      }
      if (cashInfo.trade_status) {
        return this.getBaseResult(1004004, "已经发起提现，不可作废");
      }
      if (cashInfo.qrcode_status != 2) {
        cashInfo.qrcode_status = 2;
        await cashInfo.save();
      }
    } catch (e) {
      console.log(e);
      return this.getBaseResult(500, "接口异常");
    }
    return this.getSuccessResult();
  }

  /**
   * fn:验证商户是否可用
   * @returns {Promise<void>}
   */
  async verificationMtchOutTradeNo(obj, req) {
    if (!obj || !obj.outTradeNo || !obj.mchtId || !obj.no || !obj.openId) {
      return this.getCodeResult(1002001, null);
    }
    let no = Number(await this.getNo(obj.no));
    try {
      let cashInfo = await this.ccashinfoSve.findById(no);
      console.log("verificationMtchOutTradeNo------------------------", cashInfo, no);
      if (!cashInfo || cashInfo.outTradeNo != obj.outTradeNo || cashInfo.mchtId != obj.mchtId) {
        console.log("verificationMtchOutTradeNo------------------------", obj.outTradeNo, obj.mchtId);
        return this.getErrResult("提现信息错误");
      }

      let cashUser = await this.ccashuserSve.findOne({openId: obj.openId, ecid: cashInfo.ecid});
      cashUser = cashUser || {id_name: cashInfo.id_name, id_no: cashInfo.id_no};
      let epr = {};
      if (cashInfo.ecid) {
        epr = await this.etemplateSve.allByEcid(cashInfo.ecid) || {};
      }
      let resData = {
        id_name: cashUser.id_name,
        id_no: cashUser.id_no,
        mainName: epr.main.name,
        companyName: epr.company.name
      };

      // 是否交易
      if (cashInfo.trade_status || cashInfo.qrcode_status == 2) {
        // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
        resData.redirect_code = 2;
        return this.getCodeResult(0, resData);
      }

      // 是否认证
      if (cashUser.contract_id) {
        resData.redirect_code = 3;
        return this.getCodeResult(0, resData);
      }
      // 滚去认证
      resData.redirect_code = 1;
      return this.getCodeResult(0, resData);
    } catch (e) {
      console.log(e);
      let result = {
        code: 500,
        msg: "接口异常"
      };
      console.log(e.stack);
      return result;
    }
  }

  /**
   * fn:个人要素认证
   * @returns {Promise<void>}
   */
  async authentication(obj, req) {
    if (!obj || !obj.id_name || !obj.id_no || !obj.no || !obj.openId || obj.openId == "null" || obj.openId == "undefined") {
      return this.getCodeResult(1002001, null);
    }
    let id = this.getNo(obj.no);
    try {
      let cashInfo = await this.ccashinfoSve.findById(id);
      if (!cashInfo) {
        return this.getErrResult("提现申请不存在");
      }
      if (!await this.idcardClient.checkIDCard(obj.id_no)) {
        return this.getErrResult("身份证格式不正确");
      }

      let num = await this.esettleSve.isValidAge([cashInfo.mchtId]);
      console.log("---商户年龄限制---", cashInfo.mchtId, num);
      if (num) {
        let card = await this.idcardClient.cardInfo(obj.id_no);
        console.log("---商户年龄限制---cardInfo---", cashInfo.mchtId, num, card);
        let age = card.age || 0;
        if (!age) {
          console.log("---商户年龄限制---age---", age);
          return this.getErrResult("身份证号格式错误, 只支持18位身份证号码");
        }
        if (card.sex == 'male') {
          if (age < 18 || age > 60) {
            console.log("---商户年龄限制---男性错误---");
            return this.getErrResult("签约失败，男限制18-60岁之间")
          }
        } else {
          if (age < 18 || age > 55) {
            console.log("---商户年龄限制---女性错误---");
            return this.getErrResult("签约失败，女限制18-55岁之间")
          }
        }
      }
      obj.id_no = obj.id_no.toUpperCase();

      let cashUser = await this.ccashuserSve.findOne({
        openId: obj.openId,
        ecid: cashInfo.ecid
      }) || {};

      let doAuthRes = await this.doAuth({
        id_name: this.trim(obj.id_name),
        id_no: this.trim(obj.id_no),
        app_id: obj.app_id
      });
      if (doAuthRes.status !== 0) {
        return this.getBaseResult(1, "填写姓名和身份证不匹配");
      }

      if (!cashUser.id) {
        cashUser = {};
        cashUser.cash_id = cashInfo.id;
        cashUser.ecid = cashInfo.ecid;
        cashUser.id_name = this.trim(obj.id_name);
        cashUser.id_no = this.trim(obj.id_no);
        cashUser.openId = this.trim(obj.openId);
        cashUser = await this.ccashuserSve.create(cashUser);
      }
      // console.log("调用二要素 （兰伯望） 接口返回："+JSON.stringify(doAuthRes));
      await this.doSign3(cashInfo, cashUser);

      return this.getCodeResult(0, {redirect_code: 3});
    } catch (e) {
      console.log(e);
      let result = {
        code: 500,
        msg: "接口异常"
      };
      console.log(e.stack);
      return result;
    }
  }

  /**
   * fn:打开红包
   * @param obj
   */
  async openRedEnvelopes(obj) {
    if (!obj.no) {
      return this.getBaseResult(1, 'ID不能为空');
    }
    let id = this.getNo(obj.no);
    let ccashinfo = await this.ccashinfoSve.getBean({
      id: id
    }) || {};

    let cashUser = await this.ccashuserSve.findOne({openId: obj.openId});
    if (!cashUser) {
      return this.getErrResult("用户不存在");
    }

    let key = `SDPJ_CASH_${ccashinfo.id}`;
    let _lock = uuidv1();
    try {
      if (!ccashinfo) {
        return this.getErrResult("信息不存在");
      }
      if (ccashinfo.qrcode_status == 2) {
        // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
        return this.getCodeResult(0, {redirect_code: 2});
      }
      if (ccashinfo.trade_status) {
        return this.getCodeResult(0, {redirect_code: 5});
      }

      let api = await this.ecompanybusiSve.findOne({
        appId: ccashinfo.app_id,
        etemplate_id: ccashinfo.ecid,
        mchtId: ccashinfo.mchtId,
      });

      await this.redisLock.lock(key, _lock, 20);
      let result = await this.cashOut(ccashinfo, api, cashUser);
      return result;
    } catch (e) {
      console.log(e);
      let result = {
        code: 500,
        msg: "接口异常"
      };
      console.log(e.stack);
      return result;
    } finally {
      await this.redisLock.unLock(key, _lock);
    }
  }

  async doAuth(cashInfo) {
    let res;
    // 姓名二要素
    res = await this.bankthreelogSve.personTwo({
      appId: "sdpj_sign_" + cashInfo.app_id,
      userName: cashInfo.id_name,
      userIdNo: cashInfo.id_no
    });
    return res;
  }

  async doSign3(cashInfo, cashUser) {
    let result;
    // 专票签（三方签）
    let signParam = {
      ecid: this.trim(cashInfo.ecid),
      appId: this.trim(cashInfo.app_id),
      userId: this.trim(cashUser.id_no),
      idName: this.trim(cashUser.id_name),
      idNo: this.trim(cashUser.id_no),
    };
    try {
      let key = `${cashInfo.mcthId}_${cashInfo.outTradeNo}`;
      let id = uuidv1();
      await this.redisLock.lock(key, id, 20);
      let result = await this.econtractSve.autoSignBankTwo(signParam);
      await this.redisLock.unLock(key, id);

      if (result.data && result.data.contractId) {
        cashUser.contract_id = result.data.contractId;
        cashUser.save();
      }
      return result;
    } catch (e) {
      console.log(e, cashInfo, "-----------------------签约异常-----------------------");
      return {code: 1, msg: "签约异常"};
    }
  }

  // async testCashOut() {
  //   let cashInfo = await this.ccashinfoSve.findById(22);
  //   let api = await this.ecompanybusiSve.findOne({
  //     appId: cashInfo.app_id,
  //     etemplate_id: cashInfo.ecid,
  //     mchtId: cashInfo.mchtId,
  //   });
  //
  //   let cashUser = await this.ccashuserSve.findById(1);
  //
  //   let cashRes = await this.cashOut(cashInfo, api, cashUser);
  //   console.log(cashRes);
  // }

  async cashOut(cashInfo, api, cashUser) {
    if (cashInfo.qrcode_status == 2) {
      // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
      return this.getCodeResult(0, {redirect_code: 2});
    }
    if (cashInfo.trade_status) {
      return this.getCodeResult(0, {redirect_code: 5});
    }

    console.log(`张娇要看的时间发起提现${cashInfo.outTradeNo}---------------------------`, new Date().getTime());
    // 发起交易
    let bizContent = [];
    bizContent.push({
      "note": "提现",
      "idType": "00",
      "idName": cashUser.id_name,
      "seqNo": "1000",
      "accNo": cashUser.openId,
      "amt": cashInfo.amt,
      "accType": "02",
      "idNo": cashUser.id_no
    });
    let nonceStr = await this.getUidStr(32, 36);
    let tradeTime = moment().format('YYYYMMDDHHmmss');
    let param = {
      "appId": cashInfo.app_id,
      "currency": "CNY",
      "mchtId": cashInfo.mchtId,
      "nonceStr": nonceStr,
      "notityUrl": "https://bpohhr.gongsibao.com/api/bpoSDPJApi/wxnotify",
      // "notityUrl": "https://bpohhr.gongsibao.com/api/econtractApi/transferNotify",
      "outTradeNo": cashInfo.outTradeNo,
      "signType": "MD5",
      "tradeTime": tradeTime,
      "bizContent": bizContent,
    };

    cashInfo.openId = cashUser.openId;
    cashInfo.id_name = cashUser.id_name;
    cashInfo.id_no = cashUser.id_no;
    cashInfo.save();

    // now
    let signArr = [];
    signArr.push("appId=" + param.appId);
    signArr.push("currency=" + param.currency);
    signArr.push("mchtId=" + param.mchtId);
    signArr.push("nonceStr=" + param.nonceStr);
    signArr.push("notityUrl=" + param.notityUrl);
    signArr.push("outTradeNo=" + param.outTradeNo);
    signArr.push("signType=" + param.signType);
    signArr.push("tradeTime=" + param.tradeTime);
    signArr.push("key=" + api.key);
    param.sign = md5(signArr.join("&")).toUpperCase();
    console.log(JSON.stringify(param));

    try {
      let url = settings.apiconfig.payDomain(api.env) + "/merchant/order/transfer";
      console.log("-----request smart transfer ------------" + param.outTradeNo, url, param);
      let rs = await axios({
        method: 'post',
        url: url,
        data: param,
      });
      console.log("-----response smart transfer ------------" + param.outTradeNo, rs.data);
      if (rs.data.code === 0) {
        cashInfo.trade_status = "01";
        cashInfo.trade_desc = "领取中";
        try {
          // 张娇强烈要求
          let item = await this.getActualAmt(cashInfo, api);
          cashInfo.actual_amt = item.actualAmt || 0;
        } catch (eeee) {
          console.log(eeee);
        }
        await cashInfo.save();
        // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
        return this.getSuccessResult("领取中", {redirect_code: 4});
      } else {
        cashInfo.trade_status = "02";
        cashInfo.trade_desc = rs.data.msg || "";
        let tip = this.getWxResult(cashInfo.trade_desc);
        await cashInfo.save();
        this.notifyCash(cashInfo.id);
        return this.getSuccessResult(tip, {redirect_code: 6});
      }
    } catch (error) {
      console.log(error);
      return this.getErrResult("接口异常");
    }
  }

  async checkCash(obj, req) {
    let id = Number(this.getNo(obj.no) || 0);
    let cashInfo = await this.ccashinfoSve.findById(id);

    // 查是否成功
    let api = await this.ecompanybusiSve.findOne({
      appId: cashInfo.app_id,
      etemplate_id: cashInfo.ecid,
      mchtId: cashInfo.mchtId,
    });
    let item = await this.getActualAmt(cashInfo, api);
    cashInfo.actual_amt = item.actualAmt || 0;

    console.log("查smart ------------------", id, item, new Date().getTime());
    // let actualAmt = await this.getActualAmt(cashInfo, api);
    // cashInfo.actual_amt = actualAmt;
    // await cashInfo.save();

    if (item.tradeStatus == "00" || item.tradeStatus == "02" || item.tradeStatus == "03") {
      // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
      let rc;
      let trade_desc;
      if (item.tradeStatus == "00") {
        rc = 4;
        trade_desc = "领取成功";
      } else {
        rc = 6;
        trade_desc = item.respDesc || "";
      }
      let tip = this.getWxResult(trade_desc);
      return this.getBaseResult(0, tip, {
        redirect_code: rc,
        trade_desc: cashInfo.trade_desc,
        complete: true,
        actual_amt: system.f2y(cashInfo.actual_amt)
      });
    }
    // 1 认证页面 2 二维码已失效 3 红包领取页面 4 红包领取结果页面（心跳查询） 5 红包已被领取
    return this.getBaseResult(0, "交易未完成", {complete: false, actual_amt: system.f2y(cashInfo.actual_amt)});
  }

  // async testCashOutResult(obj, req) {
  //   let cashInfo = await this.ccashinfoSve.findById(obj.id);
  //   let api = await this.ecompanybusiSve.findOne({
  //     appId: cashInfo.app_id,
  //     etemplate_id: cashInfo.ecid,
  //     mchtId: cashInfo.mchtId,
  //   });
  //   let item = await this.getActualAmt(cashInfo, api);
  //   cashInfo.actual_amt = item.actualAmt || 0;
  //   await cashInfo.save();
  //   return cashInfo;
  // }

  async testCashAmtTaskMoreIds(obj, req) {
    let lessId = Number(obj.lessId || 0);
    let mchtId = obj.mchtId || "";
    let limit = Number(obj.limit || 0);
    let ids = await this.ccashinfoSve.moreIds(lessId, mchtId, limit);

    if (!ids || ids.length == 0) {
      return "";
    }
    for (let id of ids) {
      try {
        await this.syncOneCashAmt(id.id);
      } catch (e) {
        console.log('------------testCashAmtTaskByIds------------error', e);
      }
    }
    return "生成中";
  }


  async testCashAmtTaskByIds(obj, req) {
    let ids = obj.ids;
    if (!ids || ids.length == 0) {
      return "";
    }
    for (let id of ids) {
      try {
        await this.syncOneCashAmt(id);
      } catch (e) {
        console.log('------------testCashAmtTaskByIds------------error', e);
      }
    }
    return "生成中";
  }

  async syncOneCashAmt(id) {
    try {
      console.log('------------syncOneCashAmt------------ id = ', id);
      let cashInfo = await this.ccashinfoSve.findById(id);
      let api = await this.ecompanybusiSve.findOne({
        appId: cashInfo.app_id,
        etemplate_id: cashInfo.ecid,
        mchtId: cashInfo.mchtId,
      });
      await this.syncCashAmt(cashInfo, api);
      return cashInfo;
    } catch (e) {
      console.log('------------syncOneCashAmt------------error', e);
    }
  }

  async syncCashAmt(cashInfo, api) {
    try {
      let item = await this.getActualAmt(cashInfo, api);
      console.log(item);
      if (!item || !item.amt) {
        return;
      }
      cashInfo.deduct_amt = item.deductAmt;
      cashInfo.income_tax = item.incomeTax;
      cashInfo.service_tax = item.serviceTax;
      cashInfo.added_value_tax = item.addedValueTax;
      await cashInfo.save();
    } catch (e) {
      console.log('------------syncCashAmt------------error', e);
    }
  }

  async getActualAmt(cashInfo, api) {
    let params = {
      "appId": cashInfo.app_id,
      "mchtId": cashInfo.mchtId,
      "nonceStr": await this.getUidStr(32, 36),
      "currency": "CNY",
      "outTradeNo": cashInfo.outTradeNo,
      "seqNo": "1000",
      "signType": "MD5",
    };

    let url = settings.apiconfig.payDomain(api.env) + "/merchant/order/query";
    params.sign = system.getSign(params, api.key, this.EXCEPT_KEYS);
    console.log("-----request smart query ------------", url, params);
    let rs = await axios({
      method: 'post',
      url: url,
      data: params,
    });
    console.log("-----response smart query ------------", rs.data);
    if (rs.status == 200 && rs.data.code == 0) {
      let bizArr = (rs.data.data || {}).bizContent || [];
      if (bizArr.length > 0) {
        let item = bizArr[0] || {};
        return item;
      }
    }
    return {};
  }

  async getUidStr(len, radix) {
    var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    var uuid = [],
      i;
    radix = radix || chars.length;
    if (len) {
      for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
    } else {
      var r;
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random() * 16;
          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
        }
      }
    }
    return uuid.join('');
  }

  async wxnotify(obj, req) {
    console.log(`张娇要看的时间发起提现${obj.outTradeNo}回调时间---------------------------`, new Date().getTime());
    console.log("------------- wx-sdpj转账回调 --------------", obj);
    try {
      // 1. 获取转账二维码信息
      let cashInfo = await this.ccashinfoSve.findOne({
        app_id: obj.appId,
        mchtId: obj.busiId,
        outTradeNo: obj.outTradeNo,
      });
      if (!cashInfo) {
        console.log("------------- wx-sdpj转账回调 cashInfo不存在--------------");
        return {code: ""};
      }
      if (cashInfo.trade_status == "00") {
        return {code: "0000"};
      }

      console.log("------------- wx-sdpj转账回调 cashInfo --------------", cashInfo);

      // 获取商户api信息
      let api = await this.ecompanybusiSve.findOne({
        appId: cashInfo.app_id,
        etemplate_id: cashInfo.ecid,
        mchtId: cashInfo.mchtId,
      });
      console.log("------------- wx-sdpj转账回调 api --------------", api);
      if (!api) {
        console.log("------------- wx-sdpj转账回调 api不存在--------------");
        return {code: ""};
      }

      // 验证签名
      let sign = system.getSign(obj, api.key, this.EXCEPT_KEYS);
      console.log("------------- wx-sdpj转账回调 签名 --------------", obj.sign, sign);
      if (sign != obj.sign) {
        console.log("------------- wx-sdpj转账回调 签名错误 --------------");
        return {code: ""};
      }
      cashInfo.trade_notify_time = new Date();
      // 回调逻辑判断
      let respTradeStatus = this.trim(obj.tradeStatus);
      if (respTradeStatus == "00") {
        cashInfo.trade_status = "00";
        cashInfo.trade_desc = "交易成功";
        await cashInfo.save();
        await this.notifyCash(cashInfo.id);
        await this.syncOneCashAmt(cashInfo.id);
        return {code: "0000"};
      } else if (respTradeStatus == "02" || respTradeStatus == "03") {
        cashInfo.trade_status = "02";
        cashInfo.trade_desc = obj.respDesc || "交易失败";
        await cashInfo.save();
        await this.notifyCash(cashInfo.id);
      } else {
      }
      this.syncOneCashAmt(cashInfo.id);
      return {code: ""};
    } catch (e) {
      console.log(e);
    }
  }

  // 推送回调
  async notifyGuestById(obj, req) {
    let res = await this.notifyCash(obj.no);
    return this.getBaseResult(0, "调用成功", res);
  }

  // 推送回调批量
  async notifyGuestByIds(obj, req) {
    let result = {};
    let ids = obj.ids;
    for (let id of ids) {
      try {
        result[id] = await this.notifyCash(id);
      } catch (e) {
        console.log("notifyGuestByIds---error", id, e);
      }
    }
    return result;
  }

  // 推送回调
  async notifyCash(id) {
    try { // 签名验证
      if (!id) {
        return this.getErrResult("ID不能为空");
      }
      let ccashinfo = await this.ccashinfoSve.findOne({
        id: id
      });
      // if(!ccashinfo.app_id){
      //   return this.getErrResult("app_id不能为空");
      // }
      // if(!ccashinfo.ecid){
      //   return this.getErrResult("ecid不能为空");
      // }
      // if(!ccashinfo.outTradeNo){
      //   return this.getErrResult("outTradeNo不能为空");
      // }
      // if(!ccashinfo.amt){
      //   return this.getErrResult("amt不能为空");
      // }
      // if(!ccashinfo.id_name){
      //   return this.getErrResult("id_name不能为空");
      // }
      // if(!ccashinfo.id_no){
      //   return this.getErrResult("id_no不能为空");
      // }
      if (!ccashinfo.notify_url) {
        return this.getErrResult("notify_url不能为空");
      }
      // 获取api信息
      let api = await this.ecompanybusiSve.findOne({
        appId: ccashinfo.app_id,
        etemplate_id: ccashinfo.ecid,
        mchtId: ccashinfo.mchtId,
      });
      if (!api) {
        return this.getBaseResult(1001003, "配置信息错误，请联系薪必果人员进行配置");
      }

      let param = {
        appId: ccashinfo.app_id,
        ecid: ccashinfo.ecid,
        outTradeNo: ccashinfo.outTradeNo,
        amt: ccashinfo.amt,
        idName: ccashinfo.id_name,
        idNo: ccashinfo.id_no,
        tradeStatus: ccashinfo.trade_status,
        tradeDesc: ccashinfo.trade_desc,
        nonceStr: await this.getUidStr(32, 36),
      };
      let sign = system.getSign(param, api.key, this.EXCEPT_KEYS)
      param.sign = sign;

      console.log(`---推送---${ccashinfo.outTradeNo}--begin----`, ccashinfo.notify_url, param);
      let rs = await axios({
        method: 'post',
        url: ccashinfo.notify_url,
        data: param,
      });
      console.log(`---推送---${ccashinfo.outTradeNo}--result----`, rs.data);

      let notifyRes = JSON.stringify(rs.data);
      if (notifyRes.length > 800) {
        notifyRes = notifyRes.substring(0, 790) + "...";
      }
      ccashinfo.notify_rs = notifyRes;
      await ccashinfo.save();

      return rs.data;
    } catch (e) {
      console.log(e);
      let result = {
        code: 500,
        msg: "接口异常"
      };
      console.log("---推送异常---", id, e.stack);
      return result;
    }
  }

  getSuccessResult(msg = "success", data = {}) {
    return this.getBaseResult(0, msg, data);
  }

  getCodeResult(code, data = {}) {
    return this.getBaseResult(code, this.resultMap[code], data);
  }

  getErrResult(msg) {
    return this.getBaseResult(1, msg);
  }

  getBaseResult(code, msg, data) {
    let res = {
      "code": code,
      "msg": msg,
      "data": data
    };
    return res;
  }
}

module.exports = BpoSDPJApi;
