var system = require("../../system")
const md5 = require("md5");
const moment = require("moment");
const axios = require("axios");

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.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.tdevApi = require("./tdevApi");
    this.redisLock = system.getObject("util.redisLock");
    this.bankthreelogSve = system.getObject("service.bankthreelogSve");
    this.resultMap = {
      0:"操作成功",
      1:"操作失败",
      1001001:"签名失败",
      1002001:"参数错误",
      500:"接口异常",
    }
  }
  trim(o) {
    if(!o) {
      return "";
    }
    return o.toString().trim();
  }

  /**
   * 生成二维码
   * @param obj
   * @param req
   * @returns {Promise<{msg: string, code: number}>}
   */
  async cashQRCode(obj, req) {
    // 验证合法性
    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
    };
    let api = await this.ecompanybusiSve.findOne({
      appId: obj.appId,
      etemplate_id: obj.ecid,
      mchtId: obj.mchtId,
    });
    if (!api) {
      return this.getBaseResult(1001003, "配置信息错误，请联系薪必果人员进行配置");
    }

    let keys = Object.keys(param).sort();
    let signArr = [];
    for (let k = 0; k < keys.length; k++) {
      let tKey = keys[k];
      if (this.EXCEPT_KEYS.indexOf(tKey) == -1 && param[tKey]) {
        signArr.push(tKey + "=" + param[tKey]);
      }
    }

    let signStr = signArr.join("&") + "&key=" + api.key;
    let sign = md5(signStr).toUpperCase();

    console.log(obj.sign, signStr, sign);

    if (sign != obj.sign) {
      return this.getBaseResult(1001001, "签名失败");
    }
    try {
      if(!obj || !obj.outTradeNo || !obj.mchtId){
        return this.getCodeResult(1002001,null);
      }
      //1.mchtId & ecid 进行联合查询 如果存在直接返回
      let _cCashInfo = await  this.ccashinfoSve.getBean(obj);
      console.log(`bpoSDPJApi.js -> cashQRCode -> mchtId & ecid 进行联合查询 :参数=` + JSON.stringify(obj) + "  _cCashInfo = " + JSON.stringify(_cCashInfo));
      //如果二维码有效直接返回
      if(_cCashInfo.qrcode_status &&  _cCashInfo.qrcode){
        return this.getCodeResult(0,{"qrcode": _cCashInfo.qrcode});
      }
      //如果二维码没有 可以继续生成二维码
      if(_cCashInfo && _cCashInfo.qrcode){
        return this.getCodeResult(1002001,null);
      }
      //2.检验所有参数是否完整 如果出现非法参数直接返回
      if(!obj.ecid || !obj.appId || !obj.amt){
        return this.getCodeResult(1002001,null);
      }
      //3.获取签约类型
      let _ecompanybusi = await this.ecompanybusiDao.model.findOne({
        where:{
          appId: this.trim(obj.appId),
          mchtId: this.trim(obj.mchtId)
        }
      });
      console.log("查看签约类型 _ecompanybusi=" + JSON.stringify(_ecompanybusi));
      if(!_ecompanybusi || !_ecompanybusi.dataValues.hasOwnProperty("app_type")){
        return this.getCodeResult(500,null);
      }
      let _ccashinfoProperty = {};
      _ccashinfoProperty.app_type = _ecompanybusi.app_type;
      _ccashinfoProperty.outTradeNo = obj.outTradeNo;
      _ccashinfoProperty.mchtId = obj.mchtId;
      _ccashinfoProperty.ecid = _ecompanybusi.etemplate_id;
      _ccashinfoProperty.app_id = obj.appId;
      _ccashinfoProperty.amt = Number(obj.amt || 0);
      _ccashinfoProperty.idName = this.trim(obj.idName) || "";
      _ccashinfoProperty.idNo = this.trim(obj.idNo) || "" ;

      //4.保存签约数据
      _cCashInfo = await this.ccashinfoSve.save(_ccashinfoProperty);
      if(!_cCashInfo){
        return this.getCodeResult(500,null);
      }
      //5. 拼接h5 http连接 http//xxx?mchtId=xxx&ecid=xxx&no=id
      let _no = await this.setNo(_cCashInfo.id);
      let custormUrl = `http://bpohhr.gongsibao.com?no=${_no}&outTradeNo=${_cCashInfo.outTradeNo}&mchtId=${_cCashInfo.mchtId}`;
      //6.生成二维码
      let url =await this.qrClient.generateQR(custormUrl);
      _cCashInfo.qrcode=url;
      _cCashInfo.qrcode_status=url?1:2;
      _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;
    }
  }

  async setNo(no){
    return no;
  }

  async getNo(no) {
    return no;
  }

  /**
   * fn:验证商户是否可用
   * @returns {Promise<void>}
   */
  async verificationMtchOutTradeNo(obj, req){
    if(!obj || !obj.outTradeNo || !obj.mchtId || !obj.no){
      return this.getCodeResult(1002001,null);
    }
    let no = await this.getNo(obj.no);
    try {
      let _cCashInfo = await  this.ccashinfoSve.getBean({
        id: no,
        outTradeNo: this.trim(obj.outTradeNo),
        mchtId: this.trim(obj.mchtId),
      });
      return this.getCodeResult(0,{
        id_name:_cCashInfo.id_name,
        id_no:_cCashInfo.id_no,
        app_id: _cCashInfo.app_id,
        id:_cCashInfo.id
      })
    }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.mchtId || !obj.app_id|| !obj.id){
      return this.getCodeResult(1002001,null);
    }
    try{

      let ccashinfo = await this.dao.findOne({
        where:{
          id:obj.id,
          mchtId:obj.mchId,
          outTradeNo:obj.outTradeNo
        }
      });
      if(!ccashinfo){
        this.getErrResult("信息不存在");
      }
      if (!await this.idcardClient.checkIDCard(obj.id_no)) {
        return this.returnjson(-1, "身份证格式不正确");
      }

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

      /**
       * TODO:需要线上测试
       */
      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, doAuthRes.msg || "姓名或身份证错误");
      }
      console.log("调用二要素 （兰伯望） 接口返回："+JSON.stringify(doAuthRes));
      this.doSign3(ccashinfo);

      //异步推送信息
      pushAsync(obj);

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

  }

  /**
   * fn:异步同送信息
   * @param params
   */
  pushAsync(params){



    /**
     * fn:签约
     */
    let res = this.tdevApi.doSign3(params);

    /**
     * fn:更新验证信息 人名 身份证号
     */
    this.ccashinfoSve.update(params);

  }

  /**
   * fn:打开红包
   * @param obj
   */
  openRedEnvelopes(obj){

  }


  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, params) {
    let result;
    // 专票签（三方签）
    let signParam = {
      ecid: this.trim(cashInfo.ecid),
      appId: this.trim(cashInfo.app_id),
      userId: this.trim(cashInfo.id_no),
      idName: this.trim(cashInfo.id_name),
      idNo: this.trim(cashInfo.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(params);
      await this.redisLock.unLock(key, id);

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

  async cashOut(cashInfo) {
    // 发起交易
    let bizContent = [];
    bizContent.push({
      "note": "提现",
      "idType": "00",
      "idName": cashInfo.id_name,
      "seqNo": "1000",
      "accNo": cashInfo.openId,
      "amt": cashInfo.amt,
      "accType": "00",
      "idNo": cashInfo.id_no
    });
    let nonceStr = await this.getUidStr(32, 36);
    let tradeTime = moment().format('YYYYMMDDHHmmss');
    var param = {
      "appId": cashInfo.app_id,
      "currency": "CNY",
      "mchtId": cashInfo.mchtId,
      "nonceStr": nonceStr,
      "notityUrl": "https://bpohhr.gongsibao.com/api/econtractApi/transferNotify",
      "outTradeNo": cashInfo.outTradeNo,
      "signType": "MD5",
      "tradeTime": tradeTime,
      "bizContent": bizContent,
    }

    // 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=" + mcht.secret);
    param.sign = md5(signArr.join("&")).toUpperCase();
    console.log(JSON.stringify(param));

    try {
      let rs = await axios({
        method: 'post',
        url: "https://pay.gongsibao.com/merchant/order/transfer",
        data: param,
      });
      if (rs.data.code === 0) {
        return this.getSuccessResult("提现成功");
      }
      console.log(rs.data);
      return this.getCodeResult(rs.data.msg);
    } catch (error) {
      console.log(error);
      // 发起失败，删除trade
    }
  }

  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('');
  }

  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 = 0, msg = "", data = {}) {
    let res = {
      "code": code,
      "msg": msg,
      "data": data
    }
    return res;
  }
}
module.exports = BpoSDPJApi;
