const system = require("../../system");
const ServiceBase = require("../sve.base");
const logCtl = system.getObject("web.oplogCtl");

const crypto = require('crypto');
const cryptoJS = require("crypto-js");
const md5 = require("MD5");

class EcontractService extends ServiceBase {
  constructor() {
    super(ServiceBase.getDaoName(EcontractService));
    this.ecompanyDao = system.getObject("db.ecompanyDao");
    this.usereaccountDao = system.getObject("db.usereaccountDao")
    this.restClient = system.getObject("util.restClient");
    this.utilesignbaoSve = system.getObject("service.utilesignbaoSve");
  }

  async findInfo(obj) {
    obj = obj || {};
    let v = [{
        model: this.db.models.ecompany,
        attributes: ["id", "name"]
      },
      {
        model: this.db.models.user,
        attributes: ["id", "userName", "mobile", "personsSign"]
      },
      {
        model: this.db.models.usereaccount,
        attributes: ["id", "userName", "mobile", "personsSign"]
      },
      {
        model: this.db.models.etemplate,
        attributes: ["id", "name"]
      }
    ];
    var result = await this.dao.model.findOne({
      where: obj,
      include: v
    });
    return result;
  }

  async findContracts(obj) {
    obj = obj || {};
    let v = [{
        model: this.db.models.ecompany,
        attributes: ["id", "name"]
      },
      {
        model: this.db.models.user,
        attributes: ["id", "userName", "mobile", "personsSign"]
      },
      {
        model: this.db.models.usereaccount,
        attributes: ["id", "userName", "mobile", "personsSign"]
      },
      {
        model: this.db.models.etemplate,
        attributes: ["id", "name"]
      }
    ];
    var result = await this.dao.model.findAll({
      where: obj,
      include: v
    });
    return result;
  }

  async findUserSinedCompanyIds(usereaccount_id) {
    return this.dao.findUserSinedCompanyIds(usereaccount_id);
  }

  async updateCallbackStatus(obj) {
    obj = obj || {};

    logCtl.info({
      optitle: "e签宝回调修改合同信息info",
      op: "app/base/service/impl/econtractSve/updateCallbackStatus",
      content: "请求参数：" + JSON.stringify(obj),
      clientIp: ""
    });

    let contract;
    try {
      let signTime = obj.signTime;
      let signResult = obj.signResult || "1";
      let thirdOrderNo = Number(obj.thirdOrderNo || 0);

      contract = await super.findById(thirdOrderNo);
      if (!contract) {
        return;
      }

      contract.eflowstatus = signResult.toString();
      contract.completed_at = signTime;
      contract.begin_at = signTime;
      contract.resultDescription = obj.resultDescription || "";
      var end_at = new Date(signTime);
      end_at.setFullYear(end_at.getFullYear() + 1);
      contract.end_at = end_at;

      await contract.save();

      if (signResult == "2") {
        // TODO WANGKUN 改定时任务获取
        // let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
        // console.log(fileRs, "===============================================================");
        // if(fileRs.code == 1 && fileRs.data.selfossUrl) {
        //   contract.fileurl = fileRs.data.selfossUrl;
        //   contract.save();
        // }
        this.syncContract(contract.id);
      }
    } catch (e) {
      logCtl.error({
        optitle: "e签宝回调修改合同信息error",
        op: "app/base/service/impl/econtractSve/updateCallbackStatus",
        content: "错误信息：" + e.stack,
        clientIp: ""
      });
    }
    return contract;
  }

  async pushArr(company, clist, keyHex, ivHex) {
    console.log(clist.length, "=====================推送数据=====================================");
    //data加密
    var cipherDataStr = JSON.stringify(clist);
    var _d = cryptoJS.TripleDES.encrypt(cipherDataStr, keyHex, {
      iv: ivHex
    }).toString();
    var cipherData = encodeURIComponent(_d);
    let postData = "md5=" + md5(_d) + "&data=" + cipherData
    console.log(postData, "=========================post Data========================================");
    try {
      // let rs = await this.restClient.execPost({md5:md5(cipherData), data : cipherData}, company.posturl);
      let rs = await this.restClient.execPostForm(postData, company.posturl);
      if (rs.stdout) {
        console.log(rs.stdout, "=====================推送返回值=====================================");
        let rsData = JSON.parse(rs.stdout);
        if (Number(rsData.code || 0) == 0) {
          // 更新push状态
          for (let item of clist) {
            await this.dao.updateByWhere({
              isPush: true
            }, {
              where: {
                id: item.dataId
              }
            });
          }
        }
      } else {
        logCtl.error({
          optitle: "curl pos 推送（" + company.name + ", [" + JSON.stringify(errIds) + "]）合同签署人信息, 无返回信息异常error",
          op: "/app/base/service/impl/econtractSve.js",
          content: e.stack,
          clientIp: ""
        });
      }
    } catch (e) {
      console.error(e);
      let errIds = [];
      for (let c of clist) {
        errIds.push(c.dataId);
      }
      logCtl.error({
        optitle: "curl pos 推送（" + company.name + ", [" + JSON.stringify(errIds) + "]）合同签署人信息, 操作异常异常error",
        op: "/app/base/service/impl/econtractSve.js",
        content: e.stack,
        clientIp: ""
      });
    }
  }
  async pushContract() {
    var sql = "select id from ecompany where isEnabled = 1 ";
    let companyList = await this.ecompanyDao.model.findAll({
      where: {
        isEnabled: true
      }
    });
    var rs = [];
    for (let company of companyList) {
      let deskey = company.encryptkey || ""
      let posturl = company.posturl;
      if (deskey.length <= 8 || !posturl) {
        continue;
      }
      // company.posturl = "http://192.168.18.102:8080/gongsibao-web/web/common/reviceData";
      var sql = "SELECT " +
        "t1.id, t1.etemplate_id, t1.`name`, t1.`eflowstatus`, t1.`eflowstatusname`, t2.`mobile`, t2.`userName`, t2.`personsSign`, t1.`created_at`, t1.`completed_at`, t1.`end_at` " +
        "FROM c_econtract t1 " +
        "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` WHERE t1.isPush = 0 AND t1.`eflowstatus` = '2' AND t1.ecompany_id = " + company.id;

      var list = await this.dao.customQuery(sql);
      if (!list || list.length == 0) {
        continue;
      }

      let keyHex = cryptoJS.enc.Utf8.parse(deskey);
      let ivHex = cryptoJS.enc.Utf8.parse(deskey.substring(0, 8));

      var clist = [];
      for (let item of list) {
        let completeTime = item.completed_at || "";
        if (completeTime) {
          completeTime = completeTime.Format("yyyy-MM-dd hh:mm:ss")
        }
        let invalidTime = item.end_at || "";
        if (invalidTime) {
          invalidTime = invalidTime.Format("yyyy-MM-dd hh:mm:ss")
        }
        clist.push({
          "dataId": item.id,
          "agreementId": item.etemplate_id,
          "contractName": item.name,
          "companyName": company.name,
          "statusName": item.eflowstatusname,
          "mobile": item.mobile,
          "userName": item.userName,
          "mobile": item.mobile,
          "idCard": item.personsSign,
          "beginTime": item.created_at.Format("yyyy-MM-dd hh:mm:ss"),
          "completeTime": completeTime,
          "invalidTime": invalidTime
        });
        if (clist.length >= 2) {
          await this.pushArr(company, clist, keyHex, ivHex);
          clist = [];
        }
      }

      if (clist.length > 0) {
        await this.pushArr(company, clist, keyHex, ivHex);
      }
    }
    return rs;
  }

  async downloadCompleteUrl(limit) {
    var sql = "SELECT id FROM `c_econtract` WHERE eflowstatus = '2' AND (fileurl IS NULL OR fileurl = '')  ORDER BY id DESC ";
    if (limit) {
      sql = sql + " LIMIT " + limit;
    }
    var list = await this.dao.customQuery(sql);

    if (!list || list.length == 0) {
      return;
    }

    for (var o of list) {
      var id = o.id;
      try {
        var contract = await this.dao.findById(id);
        if (!contract) {
          continue;
        }

        if (contract.eflowstatus != "2") {
          continue;
        }

        if (!contract.fileurl) {
          //  请求文件地址
          let fileRs = await this.utilesignbaoSve.downloadUserContractFile(contract.eflowid, "econtractSve");
          console.log(fileRs, "===============================================================");
          if (fileRs.code == 1 && fileRs.data.selfossUrl) {
            contract.fileurl = fileRs.data.selfossUrl;
            contract.save();
          }
        }
      } catch (e) {
        console.error(e);
        //日志记录
        logCtl.error({
          optitle: "定时下载合同任务异常, id=" + id,
          op: "app/base/service/impl/econtractSve.js",
          content: e.stack,
          clientIp: ""
        });
        return {
          code: -200,
          message: "error",
          data: {}
        };
      }
    }
  }

  async fiterSignedCards(ecompanyId, cardList) {
    var sql = "SELECT t2.`personsSign` FROM c_econtract t1 " +
      "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
      "WHERE t2.`personsSign` IN (:cardList) AND t1.`ecompany_id` = :ecompanyId AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW() " +
      "GROUP BY t2.`personsSign` ";

    var list = await this.dao.customQuery(sql, {
      ecompanyId: ecompanyId,
      cardList: cardList
    });
    var rs = [];
    if (list) {
      for (var item of list) {
        rs.push(item.personsSign);
      }
    }
    return rs;
  }

  async findSignedUsers(ecompanyId, minId, pageSize) {
    var sql = "SELECT t1.id, t2.userName, t2.mobile ,t2.`personsSign` AS idCard, t1.completed_at AS signTime, t1.end_at AS endTime FROM c_econtract t1 " +
      "INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
      "WHERE t1.id > :minId AND t1.`ecompany_id` = :ecompanyId AND t1.`eflowstatus` = '2' AND t1.`end_at`>= NOW() " +
      "ORDER BY t1.id ASC LIMIT :pageSize ";

    var list = await this.dao.customQuery(sql, {
      ecompanyId: ecompanyId,
      minId: minId,
      pageSize: pageSize
    });
    for (var item of list) {
      item.endTime = await this.formateTime(item.endTime);
      item.signTime = await this.formateTime(item.signTime);
    }
    return list;
  }

  async syncAllSigners() {
    var sql = "SELECT t1.id FROM `c_econtract` t1 " +
        " INNER JOIN p_user_eaccount t2 ON t1.`usereaccount_id` = t2.`id` " +
        " WHERE t1.`eflowstatus` = '2' AND t1.syncCode <> '0' AND t1.syncCode <> '10010000' " +
        " GROUP BY t2.`personsSign` ORDER BY t1.`id` ASC ";
    var ids = await this.dao.customQuery(sql);

    for (var c of ids) {
      try {
        await this.syncContract(c.id);
      } catch (error) {
        console.error(error);
      }
    }
  }

  async syncContract(id) {
    var contract = null;
    var account = null;
    var company = null;
    var signArr = null;
    try {
      contract = await this.dao.findById(id);
      if(!contract) {
        return null;
      }
      account = await this.usereaccountDao.findById(contract.usereaccount_id);
      if(!account) {
        return null;
      }
      company = await this.ecompanyDao.findById(contract.ecompany_id);
  
      if (contract.syncCode == '0' || contract.syncCode == '10010000') {
        return null;
      }
      // 39.96.42.199 端口：80  appId:1086941347  mchtId:108694134791293777   mainId:57731585  secret:def87140063233abc
      var item = {
        "accNo": account.bankno || "",
        "appId": "1086941347",
        "beginTime": await this.formateTime2(contract.begin_at),
        "completeTime": await this.formateTime2(contract.completed_at),
        "idName": account.userName,
        "idNo": account.personsSign,
        "idType": "00",
        "invalidTime": await this.formateTime2(contract.end_at),
        "mainId": "57731585",
        "mchtId": "108694134791293777",
        "mobile": account.mobile,
        "nonceStr": await this.getUidStr(16),
        "signType": "MD5",
        "signedName": company.name
      }

      signArr = [];
      signArr.push("appId=" + (item.appId || ""));
      signArr.push("beginTime=" + (item.beginTime || ""));
      signArr.push("completeTime=" + (item.completeTime || ""));
      signArr.push("idName=" + (item.idName || ""));
      signArr.push("idNo=" + (item.idNo || ""));
      signArr.push("idType=" + (item.idType || ""));
      signArr.push("invalidTime=" + (item.invalidTime || ""));
      signArr.push("mainId=" + (item.mainId || ""));
      signArr.push("mchtId=" + (item.mchtId || ""));
      signArr.push("mobile=" + (item.mobile || ""));
      signArr.push("nonceStr=" + (item.nonceStr || ""));
      signArr.push("signType=" + (item.signType || ""));
      signArr.push("signedName=" + (item.signedName || ""));
      signArr.push("key=def87140063233abc");

      item.sign = md5(signArr.join("&")).toUpperCase();
      try {
        let rs = await this.restClient.execPost(item, "http://39.96.42.199:81/merchant/userSigned/asyncNotify");

        if (rs && rs.stdout) {
          contract.syncCode = JSON.parse(rs.stdout).code;
        } else {
          contract.syncCode = '-10501';
        }
        await contract.save();
      } catch (error) {
        contract.syncCode = '-10500';
        await contract.save();
      }
    } catch (error) {
      console.error(error);
      if (contract) {
        contract.syncCode = '-500';
        await contract.save();
      }
    }
  }

  async testtransfer(result) {
    var date = new Date().Format("yyyy-MM-dd hh:mm:ss");
    var v = result + "---" + date;
    var sql = "INSERT INTO `testtransfer` (`v`) VALUES ('" + v + "')  ";
    await this.dao.customExecAddOrPutSql(sql, {});
  }

  async formateTime(inputTime) {
    var date = new Date(inputTime);
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    m = m < 10 ? ('0' + m) : m;
    var d = date.getDate();
    d = d < 10 ? ('0' + d) : d;
    var h = date.getHours();
    h = h < 10 ? ('0' + h) : h;
    var minute = date.getMinutes();
    var second = date.getSeconds();
    minute = minute < 10 ? ('0' + minute) : minute;
    second = second < 10 ? ('0' + second) : second;
    return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
  }

  async formateTime2(inputTime) {
    if (!inputTime) {
      return '';
    }
    var date = new Date(inputTime);
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    m = m < 10 ? ('0' + m) : m;
    var d = date.getDate();
    d = d < 10 ? ('0' + d) : d;
    var h = date.getHours();
    h = h < 10 ? ('0' + h) : h;
    var minute = date.getMinutes();
    var second = date.getSeconds();
    minute = minute < 10 ? ('0' + minute) : minute;
    second = second < 10 ? ('0' + second) : second;
    return y + '' + m + '' + d + '' + h + '' + minute + '' + second;
  }

  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('');
  }
}
module.exports = EcontractService;