const system = require("../../system")
const querystring = require('querystring');
const settings = require("../../../config/settings");
const AppletBase = require("../applet.base");
const logCtl = system.getObject("web.oplogCtl");
const uuidv4 = require('uuid/v4');
const axios = require('axios');
const moment = require('moment');
const md5 = require('md5');

class LDApplet extends AppletBase {
  constructor() {
    super();
    this.ldpartnerSve = system.getObject("service.ldpartnerSve");
    this.lduserSve = system.getObject("service.lduserSve");
    this.lduserbankSve = system.getObject("service.lduserbankSve");
    this.ldusertradeSve = system.getObject("service.ldusertradeSve");
    this.esettleSve = system.getObject("service.esettleSve");
    this.econtractSve = system.getObject("service.econtractSve");
    this.userSve = system.getObject("service.userSve");
    this.usereaccountSve = system.getObject("service.usereaccountSve");
    this.ecompanySve = system.getObject("service.ecompanySve");
    this.etemplateSve = system.getObject("service.etemplateSve");
    this.utilesignbaoSve = system.getObject("service.utilesignbaoSve");
    this.esealSve = system.getObject("service.esealSve");

    this.redisClient = system.getObject("util.redisClient");
  }

  //************************************************************公共参数处理********************开始***************************************
  //验证公共参数信息
  async getLoginInfo(req) {
    let sid = req.headers["ldh5sid"] || "";
    try {
      let user = JSON.parse(await this.redisClient.get(sid + "_user"));
      let mcht = JSON.parse(await this.redisClient.get(sid + "_mcht"));
      if (!user || !mcht) {
        return;
      }
      if (user.id) {
        await this.addLoginCache("LD_H5_LOGIN_" + user.id, sid, user, mcht);
      }
      return {user: user, mcht: mcht};
    } catch (e) {
      console.log(e)
      return null;
    }
  }

  async encrypt(obj, body, req) {
    let en = system.encryption(JSON.stringify(body.key));
    console.log(en);
    return system.getErrResult2(encodeURIComponent(en))
  }

  async removeLoginCache(uk, sid) {
    await this.redisClient.delete(uk);
    await this.redisClient.delete(sid + "_user");
    await this.redisClient.delete(sid + "_mcht");
  }

  async addLoginCache(uk, sid, user, mcht) {
    await this.redisClient.setWithEx(uk, sid, 60 * 60);
    await this.redisClient.setWithEx(sid + "_user", JSON.stringify(user), 6 * 60 * 60);
    await this.redisClient.setWithEx(sid + "_mcht", JSON.stringify(mcht), 6 * 60 * 60);
  }

  async resetLoginCache(req) {
    let sid = req.headers["ldh5sid"] || "";
    let user = JSON.parse(await this.redisClient.get(sid + "_user"));
    let mcht = JSON.parse(await this.redisClient.get(sid + "_mcht"));
    user = await this.lduserSve.findById(user.id);
    mcht = await this.esettleSve.findMchtApiInfo({mchtId: mcht.mchtId});
    await this.redisClient.setWithEx(sid + "_user", JSON.stringify(user), 6 * 60 * 60);
    await this.redisClient.setWithEx(sid + "_mcht", JSON.stringify(mcht), 6 * 60 * 60);
  }

  async setLogin(user, mcht) {
    let uk = "LD_H5_LOGIN_" + user.id;
    let sid = await this.redisClient.get(uk);
    if (sid) {
      await this.removeLoginCache(uk, sid);
    }
    sid = uuidv4();
    sid = "8200962a-2e9a-4a82-a352-3f0813e8489e-" + user.id;
    await this.addLoginCache(uk, sid, user, mcht);
    return sid;
  }


  async login(query, body, req) {
    let data = body.data;
    if (!data) {
      return system.getErrResult2("登录失败");
    }
    let loginInfo;
    try {
      loginInfo = JSON.parse(system.decryption(decodeURIComponent((data))));
    } catch (e) {
      console.log(e);
      return system.getErrResult2(`登录失败${e.stack}`);
    }

    if (!loginInfo.partner) {
      return system.getErrResult2(`登录失败，缺少合作信息`);
    }

    if (!loginInfo.user_id) {
      return system.getErrResult2(`登录失败，缺少用户标识`);
    }

    if (!loginInfo.mchtId) {
      return system.getErrResult2(`登录失败，缺少商户信息`);
    }
    try {
      let mcht = await this.esettleSve.findMchtApiInfo({mchtId: loginInfo.mchtId});
      if (!mcht) {
        return system.getErrResult2(`登录失败，商户信息不存在`);
      }

      let partner = await this.ldpartnerSve.findById(loginInfo.partner);
      if (!partner) {
        return system.getErrResult2(`登录失败，未开通合作`);
      }

      let user = await this.lduserSve.loginH5({
        p_id: partner.id,
        p_user_id: loginInfo.user_id,
        p_user_balance: Number(loginInfo.balance || 0)
      });

      let sid = await this.setLogin(user, mcht);
      return system.getResult2({
        sid: sid,
        user: user
      });
    } catch (e) {
      console.log("登录异常:error*****************************************************************************");
      console.log(e.stack);
    }
  }

  async loginUser(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }
    let user = await this.lduserSve.getById(loginInfo.user.id);
    user.p_user_balance = system.f2y(user.p_user_balance);
    return system.getResult2(user);
  }

  async saveSignInfo(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }

    let p_user_name = this.trim(body.p_user_name);
    let p_user_idno = this.trim(body.p_user_idno).toUpperCase();
    let p_user_bank_name = this.trim(body.p_user_bank_name);
    let p_user_bank_no = this.trim(body.p_user_bank_no);
    let p_user_mobile = this.trim(body.p_user_mobile);

    if (!p_user_name) {
      return system.getErrResult2("请输入真实姓名");
    }
    if (!p_user_idno) {
      return system.getErrResult2("请输入您的身份证号");
    }
    if (!p_user_bank_name) {
      return system.getErrResult2("请输入开户行");
    }
    if (!p_user_bank_no) {
      return system.getErrResult2("请输入您的银行卡号");
    }
    if (!p_user_mobile) {
      return system.getErrResult2("请输入您的手机号码");
    }

    let lduser = await this.lduserSve.findById(loginInfo.user.id);
    if (lduser.econtract_id) {
      let ak47 = await this.econtractSve.findById(lduser.econtract_id);
      return system.getResult2(ak47.esignUrl);
    }

    let bankParams = {
      name: p_user_name,
      idno: p_user_idno.toUpperCase(),
      cardno: p_user_bank_no,
      mobile: p_user_mobile,
    };
    let tt = await this.utilesignbaoSve.bankfour(bankParams, "ldApplet.saveSignInfo") || {};
    console.log("threeResult-----------------------------", tt);
    if (!tt || tt.code == -120) {
      return system.getErrResult2("银行四要素（姓名、身份证、银行卡号、手机号）验证失败");
    }
    if (tt.code == -110) {
      return system.getErrResult2("银行四要素验证失败");
    }

    lduser.p_user_name = p_user_name;
    lduser.p_user_idno = p_user_idno;
    lduser.p_user_bank_name = p_user_bank_name;
    lduser.p_user_bank_no = p_user_bank_no;
    lduser.p_user_mobile = p_user_mobile;
    lduser = await lduser.save();

    let signInfo = await this.genSignUrl(lduser);
    lduser.econtract_id = signInfo.contract.id;
    lduser.is_sign = true;
    lduser = await lduser.save();
    try {
      await this.redisClient.setWithEx(req.headers["ldh5sid"] + "_user", JSON.stringify(lduser), 6 * 60 * 60);
      let b = {
        user_id: loginInfo.user.id,
        bank_user_name: p_user_name,
        bank_user_idno: p_user_idno,
        bank_name: p_user_bank_name,
        bank_no: p_user_bank_no,
      }
      let exist = await this.lduserbankSve.findOne(b);
      if (!exist) {
        await this.lduserbankSve.create(b);
      }
    } catch (e) {
      console.log(e.stack);
    }
    return system.getResult2(signInfo.signUrl);
  }

  async contract(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }

    let u = await this.lduserSve.findById(loginInfo.user.id);
    let contract = await this.econtractSve.findInfo({id: u.econtract_id});
    return system.getResult2(contract);
  }

  async genSignUserInfo(lduser) {
    let unionId = `LD_${lduser.p_id}_${lduser.id}`;
    let user = await this.userSve.findOne({
      unionId: unionId
    });
    if (!user) {
      user = await this.userSve.create({
        appkey: lduser.p_id,
        unionId: unionId,
        userId3rd: lduser.id,
        userName: lduser.p_user_name,
        mobile: lduser.p_user_mobile,
        utype: 0,
      });
    }
    let eaccount = await this.usereaccountSve.findOne({
      user_id: user.id,
      personsSign: lduser.p_user_idno
    });
    if (!eaccount) {
      eaccount = {};
      eaccount.user_id = user.id;
      eaccount.userName = lduser.p_user_name;
      eaccount.mobile = lduser.p_user_mobile;
      eaccount.bankno = lduser.p_user_bank_no;
      eaccount.personsSign = lduser.p_user_idno;
      eaccount = await this.usereaccountSve.create(eaccount);
    }
    if (!eaccount.eaccountid) {
      //创建e签宝account 5.2.1 , 创建后save()
      var params = {
        thirdId: `${unionId}_${eaccount.id}`,
        name: eaccount.userName,
        idNo: eaccount.personsSign,
        idType: 19,
        mobile: eaccount.mobile
      };
      let tt = await this.utilesignbaoSve.createAccountId(params, "userCtl");
      console.log(tt, "----------------------------------------------------tt------------ ");
      if (tt && tt.code == 1 && tt.data) {
        console.log(tt.code, "----------------------------------------tt.code------------------------ ");
        eaccount.eaccountid = tt.data.accountId;
        await eaccount.save();
      }
    }
    return {user: user, eaccount: eaccount};
  }

  async genSignUrl(lduser) {
    let partner = await this.ldpartnerSve.findById(lduser.p_id);
    let etemplateid = partner.ecid;

    let etemplate = await this.etemplateSve.findById(etemplateid);
    let company = await this.ecompanySve.findById(etemplate.ecompany_id);

    let signUserInfo = await this.genSignUserInfo(lduser);
    let user = signUserInfo.user;
    let eaccount = signUserInfo.eaccount;

    let contract = {
      name: company.name,
      etemplate_id: etemplateid,
      user_id: user.id,
      usereaccount_id: eaccount.id,
      ecompany_id: etemplate.ecompany_id,
      edocid: "",
      eflowid: "",
      esignUrl: "",
      eflowstatus: "1",
      isInsure: false,
    };

    contract = await this.econtractSve.create(contract);
    let today = new Date().Format("yyyy-MM-dd");
    let nameA = etemplate.nameA;
    let eseal = await this.esealSve.findOne({
      nameA: nameA
    });

    var sealId = "";
    if (!eseal) {
      let rs = await this.utilesignbaoSve.creatEntSignet(settings.apiconfig.companyAccountId(), nameA + "alias", nameA, "", "", "econtractCtl");
      if (rs && rs.code == 1) {
        sealId = rs.data.sealId;
        await this.esealSve.create({
          nameA: nameA,
          sealId: sealId,
        });
      } else {
        return system.getErrResult2("签约失败, 生成印章错误");
      }
    } else {
      sealId = eseal.sealId;
    }

    let params = {
      templateId: etemplate.templateid, //模板id，由创建模板接口调用返回的templateId 必填
      name: company.name, //合同模板名称 必填
      simpleFormFields: {
        nameA: nameA, //甲方 必填
        nameB: eaccount.userName, //乙方 必填
        unit: company.name, //合作单位（国美） 必填---------------------------超出长度风险---目前不知多少长度
        signDateA: today, //甲方签约日期 必填
        signDateB: today //乙方签约日期 必填
      }
    };
    let ebaoAccountId = eaccount.eaccountid; //签署人账户id-- 必填
    let thirdOrderNo = contract.id; //第三方流水号，通知回调使用---选填
    let eBaoRedirectBossUrl = "https://bpotrade.gongsibao.com";
    console.log({
      params: params,
      ebaoAccountId: ebaoAccountId,
      thirdOrderNo: thirdOrderNo
    }, "-============= params ===========================");
    let tt = await this.utilesignbaoSve.userSignContractNoTemplate(params, ebaoAccountId, thirdOrderNo, eBaoRedirectBossUrl, "ldApplet", sealId);
    console.log(tt, "-============= result ===========================");
    if (tt && tt.code == 1) {
      contract.eflowid = tt.data.flowId;
      contract.edocid = tt.data.docId;
      contract.esignUrl = tt.data.signUrl;
      contract.save();
      return {
        contract: contract,
        signUrl: contract.esignUrl,
      }
    }
    return null;
  }

  async saveBank(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }

    let bank_user_name = this.trim(body.bank_user_name);
    let bank_user_idno = this.trim(body.bank_user_idno).toUpperCase();
    let bank_name = this.trim(body.bank_name);
    let bank_no = this.trim(body.bank_no);
    if (!bank_user_name) {
      return system.getErrResult2("请填写真实姓名");
    }
    if (!bank_user_idno) {
      return system.getErrResult2("请填写身份证号码");
    }
    if (!bank_no) {
      return system.getErrResult2("请填写银行卡号");
    }
    let bankParams = {
      name: bank_user_name,
      idno: bank_user_idno,
      cardno: bank_no,
    };
    let bp = {
      user_id: loginInfo.user.id,
      bank_user_name: bank_user_name,
      bank_user_idno: bank_user_idno,
      bank_name: bank_name,
      bank_no: bank_no,
    }
    let exists = await this.lduserbankSve.create(bp);
    if (exists) {
      return system.getResult2(exists);
    }
    let tt = await this.utilesignbaoSve.bankthree(bankParams, "ldApplet.saveSignInfo") || {};
    console.log("threeResult-----------------------------", tt);
    if (!tt || tt.code == -120) {
      return system.getErrResult2("银行三要素（姓名、身份证、银行卡号）验证失败");
    }
    if (tt.code == -110) {
      return system.getErrResult2("银行三要素验证失败");
    }

    let bank = await this.lduserbankSve.create({
      user_id: loginInfo.user.id,
      bank_user_name: bank_user_name,
      bank_user_idno: bank_user_idno,
      bank_name: bank_name,
      bank_no: bank_no,
    });
    return system.getResult2(bank);
  }

  async bankList(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }

    let list = await this.lduserbankSve.listByCondition({user_id: loginInfo.user.id});
    for (let b of list) {
      b.bank_no = b.bank_no.replace(/^(\d{4})\d+(\d{4})$/, "*****$2");
    }
    return system.getResult2(list);
  }

  async cashOut(query, body, req) {
    let loginInfo = await this.getLoginInfo(req);
    if (!loginInfo) {
      return system.getErrResult2("登录过期，请重新登录");
    }
    let amt = Number(system.y2f(this.trim(body.amt)));
    let bank_id = Number(this.trim(body.bank_id));
    if (amt == 0) {
      return system.getErrResult2("请输入提现金额");
    }

    if (!bank_id) {
      return system.getErrResult2("请选择提现银行卡");
    }

    let bank = await this.lduserbankSve.findById(bank_id);
    if (!bank) {
      return system.getErrResult2(`银行卡[${bank_id}]不存在`);
    }

    let lduser = await this.lduserSve.findById(loginInfo.user.id);
    if (amt > lduser.p_user_balance) {
      return system.getErrResult2("提现金额超出余额，请重新输入");
    }

    // 查mcht
    let mcht = await this.esettleSve.findMchtApiInfo({mchtId: loginInfo.mcht.mchtId});
    if (!mcht) {
      return system.getErrResult2("用户商户错误，请重新登录");
    }

    try {
      // 生成trade
      let trade = await this.ldusertradeSve.create({
        p_id: lduser.p_id,
        user_id: lduser.id,
        amt: amt,
        trade_status: "01",
        complete_time: new Date()
      });
      // 更新用户余额
      let ubrs = await this.lduserSve.updateBalance(lduser.id, -1 * amt);
      console.log(ubrs);
      lduser = await this.lduserSve.findById(lduser.id);

      // 生成out_trade_no
      trade.out_trade_no = `LD_H5APP_${trade.user_id}_${trade.id}`;
      await trade.save();

      // 发起交易
      let bizContent = [];
      bizContent.push({
        "note": "提现",
        "idType": "00",
        "idName": bank.bank_user_name,
        "seqNo": "1000",
        "accNo": bank.bank_no,
        "mobile": lduser.p_user_mobile,
        "amt": Number(amt),
        "accType": "00",
        "idNo": bank.bank_user_idno
      });
      // mchtId, t1.`company_name` AS companyName, t2.`main_id` AS mainId, t3.id AS appId, t3.secret
      // var now = moment().add(30, 'seconds').format('YYYYMMDDHHmmss');
      let nonceStr = await this.getUidStr(20, 36);
      let tradeTime = moment().format('YYYYMMDDHHmmss');
      var param = {
        "appId": mcht.appId,
        "currency": "CNY",
        "mchtId": mcht.mchtId,
        "nonceStr": nonceStr,
        "notityUrl": "https://bpohhr.gongsibao.com/api/econtractApi/transferNotify",
        "outTradeNo": trade.out_trade_no,
        "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) {
          trade.trade_status = "00";
          await trade.save();
          await this.redisClient.setWithEx(req.headers["ldh5sid"] + "_user", JSON.stringify(lduser), 6 * 60 * 60);
          return system.getResult2("提现成功");
        }
        console.log(rs.data);
      } catch (error) {
        console.log(error);
        // 发起失败，删除trade
      }
    } catch (e) {
      console.log(e);
    }
    return system.getResult2("提现成功，稍后到账");
  }

  async tradeNotify() {

  }
}

module.exports = LDApplet;