var system = require("../../system")
var settings = require("../../../config/settings");
const CtlBase = require("../ctl.base");
const uuidv4 = require('uuid/v4');
const moment = require('moment');
const md5 = require("MD5");
const uuidv1 = require('uuid/v1');

class CWxSignApiCtl extends CtlBase {
  constructor() {
    super(CtlBase.getServiceName(CWxSignApiCtl));
    this.idcardClient = system.getObject("util.idcardClient");
    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.bankthreelogSve = system.getObject("service.bankthreelogSve");
    this.redisLock = system.getObject("util.redisLock");

    this.EXCEPT_KEYS = ['sign', 'idName'];
  }

  async checkSign(q, p, req) {
    let params = p.params || {};
    let appId = this.trim(params.appId);
    let ecid = this.trim(params.ecid);
    let nonceStr = this.trim(params.nonceStr);
    if (!nonceStr) {
      return system.getErrResult2(`签名失败，随机码不存在`);
    }
    let api = await this.service.findOne({app_id: appId, ecid: ecid});
    if (!api) {
      return system.getErrResult2(`未找到应用，请联系薪必果运维人员进行配置`);
    }

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

    let signStr = signArr.join("&") + "&key=" + api.app_secret;
    let sign = md5(signStr).toUpperCase();
    console.log(params.sign, signStr, sign);
    if (params.sign != sign) {
      return system.getErrResult2("签名验证失败");
    }
    return system.getResult2(1);
  }

  async getApiInfo(q, p, req) {
    let params = p.params || {};
    let appId = this.trim(params.appId);
    let ecid = this.trim(params.ecid);
    let api = await this.service.findOne({app_id: appId, ecid: ecid});
    if (!api) {
      return system.getErrResult2(`未找到应用，请联系薪必果运维人员进行配置`);
    }

    let company = await this.getCompanyInfo(api);
    let fieldMap = {};
    for (let f of api.form_field.split(",")) {
      fieldMap[f] = f;
    }
    let rs = {
      app_type: api.app_type,
      auth_type: api.auth_type,
      form_field: fieldMap,
    };
    for (let f in company) {
      rs[f] = company[f];
    }
    return system.getResult2(rs);
  }

  async getCompanyInfo(api) {
    let result = {};
    if (api.app_type == 1) {
      let all = await this.dktemplateSve.allByEcid(api.ecid);
      result.companyName = all.company.name;
      result.phone = all.company.phone;
      result.addr = all.company.addr;
    } else {
      let all = await this.etemplateSve.allByEcid(api.ecid);
      result.companyName = all.company.name;
      result.nameA = all.main.name;
    }
    return result;
  }


  async createApi(q, p, req) {
    try {
      // app_id
      let app_id = this.trim(p.app_id);
      if (!app_id) {
        app_id = await this.redisClient.genrateId("c_wxsign_api");
      }

      let app_secret = this.trim(p.app_secret);
      if (!app_secret) {
        app_secret = this.getUidInfo(32).toLowerCase();
      }

      let rs = await this.service.create({
        app_id: app_id,
        app_secret: app_secret
      });

      return system.getResult2(rs);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }


  // 通过用户id保存用户，目前只有北京酷酷在用
  async saveSign(q, p, req) {
    try {
      let params = p.params || {};
      params.id_no = this.trim(params.id_no).toUpperCase();
      params.appId = this.trim(params.appId);
      params.ecid = this.trim(params.ecid);
      params.idName = this.trim(params.idName);
      params.idNo = this.trim(params.idNo);
      params.mobile = this.trim(params.mobile);
      params.bankNo = this.trim(params.bankNo);
      params.userId = this.trim(params.userId);
      let api = await this.service.findOne({app_id: params.appId, ecid: params.ecid});
      if (!api) {
        return system.getErrResult2(`未找到应用，请联系薪必果运维人员进行配置`);
      }

      // 验证参数
      let checkParamsRes = await this.checkParams(params, api);
      if (checkParamsRes.status !== 0) {
        return checkParamsRes;
      }
      // 要素认证
      let authRes = await this.doAuth(params, api);
      if (authRes.status != 0) {
        return authRes;
      }

      // 插入数据库
      let signInfo = {
        api_id: api.id,
        userId: params.userId,
        openId: params.openId,
        id_name: params.idName,
        id_no: params.idNo,
        mobile: params.mobile,
        bank_no: params.bankNo,
        contract_id: 0,
      };
      signInfo = await this.cwxsigninfoSve.create(signInfo);

      // 异步签约
      await this.doSign(api, signInfo, params);

      // openId回调
      let rs = {};
      rs.redirectUrl = await this.getApiRedirectUrl(api, signInfo);
      return system.getResult2(rs);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }

  async getApiRedirectUrl(api, signInfo) {
    if (!api.redirect_url) {
      return "";
    }
    let p = {
      appId: api.app_id,
      userId: signInfo.userId,
      nonceStr: await this.getUidInfo(16),
      idName: encodeURIComponent(encodeURIComponent(signInfo.id_name)),
      openId: signInfo.openId,
      mobile: signInfo.mobile,
      idNo: signInfo.id_no,
      bankNo: signInfo.bank_no
    };

    let keys = Object.keys(p).sort();
    let signArr = [];
    for (let k = 0; k < keys.length; k++) {
      let tKey = keys[k];
      if (this.EXCEPT_KEYS.indexOf(tKey) == -1 && p[tKey]) {
        signArr.push(tKey + "=" + p[tKey]);
      }
    }
    let urlParams = signArr.join("&");
    let sign = md5(urlParams + "&key=" + api.app_secret).toUpperCase();
    console.log(urlParams, sign);
    return `${api.redirect_url}?${urlParams}&idName=${p.idName}&sign=${sign}`;
  }

  async checkParams(params, api) {
    if (!params.openId) {
      return system.getErrResult2("openid获取失败");
    }
    if (!params.idName) {
      return system.getErrResult2("请填写姓名");
    }
    if (!params.idNo) {
      return system.getErrResult2("请填写身份证号码");
    }
    if (!await this.idcardClient.checkIDCard(params.idNo)) {
      return system.getErrResult2("您的身份证号格式错误");
    }

    let card = await this.idcardClient.cardInfo(params.idNo);
    let age = card.age || 0;
    if (!age) {
      return system.getErrResult2("您的身份证号格式错误");
    }
    if (card.sex == 'male') {
      if (age < 18 || age > 60) {
        return system.getErrResult2("男性要求18-60岁");
      }
    } else {
      if (age < 18 || age > 55) {
        return system.getErrResult2("女性要求18-55岁");
      }
    }
    if (!params.userId) {
      return system.getErrResult2("用户唯一标识出错");
    }

    // auth_type 认证类型 0无认证 1姓名二要素 2银行卡三要素 3银行卡四要素
    if (api.auth_type == 2) {
      if (!params.bankNo) {
        return system.getErrResult2("请填写银行卡号");
      }
    } else if (api.auth_type == 3) {
      if (!params.bankNo) {
        return system.getErrResult2("请填写银行卡号");
      }
      if (!params.mobile) {
        return system.getErrResult2("请填写银行预留手机号");
      }
    } else {
      console.log(api, `------checkParams ${api.auth_type} else---------`)
    }
    return system.getResult2(1);
  }

  async doAuth(params, api) {
    // auth_type 认证类型 0无认证 1姓名二要素 2银行卡三要素 3银行卡四要素
    let res;
    if (api.auth_type == 1) {
      // 姓名二要素
      res = await this.bankthreelogSve.personTwo({
        appId: "wxsign_" + api.app_id,
        userName: params.idName,
        userIdNo: params.idNo
      });
      // res = system.getResult2({pass: true}); // TODO 注释掉
    } else if (api.auth_type == 2) {
      // 银行卡三要素
      res = await this.bankthreelogSve.bankThree({
        appId: "wxsign_" + api.app_id,
        userName: params.idName,
        userIdNo: params.idNo,
        userBankNo: params.bankNo,
      });
    } else if (api.auth_type == 3) {
      // 银行卡四要素
      let res = await this.bankthreelogSve.bankfour({
        appId: "wxsign_" + api.app_id,
        userName: params.idName,
        userIdNo: params.idNo,
        userBankNo: params.bankNo,
        userMobile: params.mobile,
      });
    } else {
      // 无需验证
      res = system.getResult2({pass: true});
      console.log(api, `------doAuth ${api.auth_type} else---------`)
    }
    return res;
  }

  async doSign(api, signInfo, params) {
    let key = `${api.app_id}_${params.idNo}`;
    let _lock = uuidv1();
    await this.redisLock.lock(key, _lock, 20);
    try {
      let res;
      let signParams = {
        appId: "wxsign_" + api.app_id,
        ecid: api.ecid,
        userId: signInfo.userId || "",
        idName: params.idName,
        idNo: params.idNo,
        bankno: params.bankNo,
        mobile: params.mobile,
      }
      if (api.app_type == 1) {
        // 普票签
        // let res = await this.doSign2(api, signInfo, params);
        res = await this.dkcontractSve.autoSignNew(signParams);
        if (res.code == 0) {
          signInfo.contract_id = res.data.contractId;
          signInfo.save();
        }
      } else if (api.app_type == 2) {
        // 专票签
        res = await this.econtractSve.autoSignWX(signParams);
        if (res.code == 0) {
          signInfo.contract_id = res.data.contractId;
          signInfo.save();
        }
      } else {
      }
      // 返回结果
      if (api.wx_notify_url) {
        // TODO 回调给接入方，时间不够，暂未实现
      }
    } catch (e) {
    } finally {
      await this.redisLock.unLock(key, _lock);
    }
  }

  // 通过模板id保存用户
  async saveEcidUser(q, p, req) {
    var etemplate_id = Number(p.etemplate_id);
    try {
      var template = await this.etemplateSve.findById(etemplate_id);
      var wxuser = {
        ecompany_id: Number(template.ecompany_id || 0),
        etemplate_id: Number(etemplate_id || 0),
        openId: this.trim(p.openId),
        id_no: this.trim(p.id_no || ""),
        id_name: this.trim(p.id_name || ""),
        userCode: this.trim(p.userCode || ""),
        isSend: false,
      };

      var rs = await this.service.saveEcidUser(wxuser);
      if (rs == -101) {
        return system.getErrResult2("公司还未配置签约参数");
      }

      if (rs == -201) {
        return system.getErrResult2("提交失败，您填写的身份证号码已经录入系统");
      }
      return system.getResult2(rs);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }

  async companyName(q, p, req) {
    var ecompany_id = Number(p.companyId);
    try {
      var ecompany = await this.ecompanySve.findById(ecompany_id);
      if (!ecompany) {
        return system.getErrResult2("公司名称未设置");
      }
      return system.getResult2(ecompany.name);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }

  async companyByEcid(q, p, req) {
    var ecid = Number(p.ecid);
    try {
      var etemplate = await this.etemplateSve.findById(ecid);
      var ecompany = await this.ecompanySve.findById(etemplate.ecompany_id);

      if (!ecompany || !etemplate) {
        return system.getErrResult2("公司未设置");
      }
      ecompany.etemplate = etemplate;
      return system.getResult2(ecompany);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }

  // 跟拒ecompany_id验证签名
  async validateSign(q, p, req) {
    try {
      var sign = p.sign || "";
      var companyId = p.companyId || 0;
      var nonceStr = p.nonceStr || "";
      var userCode = p.userCode || "";
      var busi = await this.ecompanybusiSve.findOne({ecompany_id: companyId});
      if (!busi) {
        return system.getErrResult2("企业未做业务开通");
      }
      var signArr = [];
      signArr.push("appId=" + busi.appId);
      signArr.push("nonceStr=" + nonceStr);
      signArr.push("userCode=" + userCode);
      signArr.push("key=" + busi.key);
      var calcSign = md5(signArr.join("&")).toUpperCase();
      if (sign != calcSign) {
        return system.getErrResult2("签名失败，请关闭页面重试。");
      }

      return system.getResult2(1);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }

  // 跟拒etemplate_id验证签名
  async validateECSign(q, p, req) {
    try {
      var sign = p.sign || "";
      var etemplateId = p.ecid || 0;
      var nonceStr = p.nonceStr || "";
      var userCode = p.userCode || "";
      var busi = await this.ecompanybusiSve.findOne({etemplate_id: etemplateId});
      if (!busi) {
        return system.getErrResult2("企业未做业务开通");
      }
      var signArr = [];
      signArr.push("appId=" + busi.appId);
      signArr.push("nonceStr=" + nonceStr);
      signArr.push("userCode=" + userCode);
      signArr.push("key=" + busi.key);
      var calcSign = md5(signArr.join("&")).toUpperCase();
      if (sign != calcSign) {
        return system.getErrResult2("签名失败，请关闭页面重试。");
      }

      return system.getResult2(1);
    } catch (e) {
      console.log(e);
      return system.getErrResult2("您的网络不稳, 请稍后重试");
    }
  }
}

module.exports = CWxSignApiCtl;
