const system = require("../../../system");
const ServiceBase = require("../../sve.base")
const settings = require("../../../../config/settings")
const jwt = require('jsonwebtoken');
class UserService extends ServiceBase {
  constructor() {
    super("auth", ServiceBase.getDaoName(UserService));
    this.companyDao = system.getObject("db.common.companyDao");
    this.roleDao = system.getObject("db.auth.roleDao");
    this.authS = system.getObject("service.auth.authSve");
  }
  async pmgetUserByCode (code) {
    let ux = await this.cacheManager["CodeCache"].getCache(code);
    return ux;
  }
  async loginApp (appkey, uname) {
    let rtn = {}
    let app = await this.cacheManager["AppCache"].cache(appkey);
    let userLogined = await this.cacheManager["UserCache"].cache(uname);
    rtn.user = userLogined

    if (userLogined) {
      let token = await this.cmakejwt(userLogined.jwtkey, userLogined.jwtsecret, null);
      rtn.token = token;
    }
    let roleids = userLogined.Roles.map(item => {
      return item.id
    })
    let auths = await this.authS.findAuthsByRole(roleids)
    rtn.user.access = auths
    let code = this.getUUID()
    this.cacheManager["CodeCache"].cache(code, rtn, 60000);
    //  let url=app.homePage+"?code="+code
    return { code, homePage: app.homePage };
  }
  //登录后的租户创建属于租户的用户
  //需要在控制器里取出公司ID
  //和租户绑定同一家公司
  //按照用户名和密码进行注册
  //控制器端检查用户名和密码非空
  async registerByTantent (p, q) {
    // 需要默认添加访客角色,为了控制单点从平台登录时看到的菜单和功能
    if (p.roles && p.roles.length > 0) {
      if (p.roles.indexOf(settings.pmroleid["pr"]) < 0) {
        p.roles.push(settings.pmroleid["pr"])
      }
    }
    p.rolecodes = (p.roles && p.roles.length > 0) ? p.roles : [settings.pmroleid["pr"]];
    let rtn = await this.pmregister(p, q)
    return rtn;
  }

  //应用的自由用户注册,无需验证，需要前端头设置公司KEY
  async pmregisterByFreeUser (p, q) {
    p.rolecodes = [settings.pmroleid["pr"]];
    let rtn = await this.pmregister(p, q)
    return rtn;
  }


  //平台租户注册接口方法
  //控制器端检查用户名和密码非空
  async pmregister (p, q) {
    var self = this;
    let tmppwd = p.password;
    if (!tmppwd) {
      tmppwd = settings.defaultpwd;
    }
    p.password = this.getEncryptStr(tmppwd);
    if (!p.nickName) {
      p.nickName = p.userName;
    }
    //检查是否已经存在同名账号
    let existOne = await this.dao.model.findOne({ where: { userName: p.userName } })
    if (existOne) {
      throw new Error("平台中已存在相同的账号.");
    }

    return this.db.transaction(async function (t) {
      //对于租户类型注册，创建一个默认公司,公司名称xxxx的公司
      //如果非租户类型,需要按照传递进来的公司companykey,来查询公司,按照companykey缓存到redis
      let cmpkey = self.getUUID();
      let rolecodes = p.rolecodes ? p.rolecodes : [settings.pmroleid["ta"]];
      if (rolecodes[0] == settings.pmroleid["ta"]) {//如果注册时，角色是租户，那么需要创建默认公司
        p.isAdmin = true;//租户默认就是管理员的权限
        let cmp = await self.companyDao.create({ name: p.userName + "的公司", companykey: cmpkey }, t);
        p.company_id = cmp.id;
      }

      //如果是用户注册，平台用户应该只属于平台应用
      let roleappid = p.app_id;//先取出当前应用的id,给后续的取角色用，角色是按照应用和公司区分
      //目前升级为角色不再按照应用区分，只按照公司区分
      p.app_id = settings.pmappid
      let u = await self.dao.create(p, t)
      //设置默认角色，租户
      //设置默认普通角色,由于有了租户概念,所以注册时，需要知道当前租户和应用的id 才可以设置默认角色 todo
      //如果是非租户，那么按照当前应用ID是找不到指定的角色，所以是空的
      /*if (p.isAdmin) {
        //var roles = await self.roleDao.model.findAll({ where: { id: { [self.db.Op.in]: rolecodes }, app_id: roleappid, company_id: settings.pmcompanyid }, transaction: t });
        var roles = await self.roleDao.model.findAll({ where: { id: { [self.db.Op.in]: rolecodes }}, transaction: t });
        if (roles && roles.length > 0) {
          await u.setRoles(roles, { transaction: t });
        }
      } else {
        var roles = await self.roleDao.model.findAll({ where: { id: { [self.db.Op.in]: rolecodes }, app_id: roleappid, company_id: p.company_id }, transaction: t });
        if (roles && roles.length > 0) {
          await u.setRoles(roles, { transaction: t });
        }
      }*/
      var roles = await self.roleDao.model.findAll({ where: { id: { [self.db.Op.in]: rolecodes } }, transaction: t });
      if (roles && roles.length > 0) {
        await u.setRoles(roles, { transaction: t });
      }

      //创建统一账号 to add extra fields
      let cred = await self.cregister(u.userName, p.company_id, p.password, u.id + "")
      console.log("......................................");
      console.log(cred.consumer.id);
      if (cred) {
        u.center_id = cred.consumer.id;
        u.jwtkey = cred.key;
        u.jwtsecret = cred.secret;

        try {
          await u.save({ transaction: t });
        } catch (e) {
          console.log(e);
          await self.cunregister(p.userName);
          throw new Error("保存用户失败");
        }
        return { user: u, companykey: cmpkey };
      } else {
        throw new Error("创建统一账号失败");
      }
    });
  }
  async logout (pobj) {
    await this.cacheManager["UserCache"].invalidate(pobj.username);
    return {}
  }
  //平台登录
  //登录接口封装kong-url
  //登录路由放行
  //p里面含有appkey,company_id,userName,password
  async pmlogin (p, q, req) {
    var self = this;
    //先要按照用户名，在统一账户中查找存在性
    //如果不存在
    console.log(UserService.consumerUrl(p.userName))
    let consumer = await this.cget(UserService.consumerUrl(p.userName));
    if (!consumer.data) {
      return null;
    } else {
      console.log(JSON.stringify(consumer.data))
      let password = consumer.data.tags[1].split("_")[1];
      let inpassword = this.getEncryptStr(p.password);
      if (password != inpassword) {
        return null;
      }
    }
    var rtn = {}
    return this.db.transaction(async function (t) {
      //从缓存中取得
      // let userfind = await self.dao.model.findOne({
      //   where: { userName: p.userName, app_id: settings.pmappid },
      //   attributes: ['userName', 'nickName','headUrl','jwtkey','jwtsecret','created_at','isSuper','isAdmin'],
      //   include: [{ model: self.db.models.company, raw: true, attributes: ["companykey"] }]
      // });
      let userfind = await self.cacheManager["UserCache"].cache(p.userName)
      if (userfind) {
        let token = await self.cmakejwt(userfind.jwtkey, userfind.jwtsecret, null);
        rtn.token = token;

        let roleids = userfind.Roles.map(item => {
          return item.id
        })
        let auths = await self.authS.findAuthsByRole(roleids)
        userfind["access"] = auths

        delete userfind["jwtkey"]
        delete userfind["jwtsecret"]
        rtn.user = userfind;
        return rtn;
      } else {
        return null;
      }
    })
  }
  async getUserInfo (uname) {
    // let userfind = await this.dao.model.findOne({
    //   where: { userName: uname, app_id: settings.pmappid },
    //   attributes: ['userName', 'nickName',"headUrl",'isSuper','isAdmin'],
    //   include: [{ model: this.db.models.company, raw: true, attributes: ["companykey"] }]
    // });
    let userfind = await this.cacheManager["UserCache"].cache(uname)
    //添加当前用户的权限信息
    let roleids = userfind.Roles.map(item => {
      return item.id
    })
    let auths = await this.authS.findAuthsByRole(roleids)
    userfind["access"] = auths

    delete userfind["jwtkey"]
    delete userfind["jwtsecret"]
    return userfind;
  }

  //自由用户的电话登录和注册
  //需要存在公司KEY
  async pmloginByVCodeForFreeUser (p, q) {
    p.rolecodes = [settings.pmroleid["pr"]];
    let rtn = await this.pmloginByVCode(p, q, req)
    return system.getResult(rtn);
  }

  //平台租户注册与登录
  //用户验证码登录
  //
  async pmloginByVCode (p, q, req) {
    var rtn = {}
    //检查传递过来的手机验证码是否与缓存的一致
    let mobile = p.mobile;
    let vcode = p.vcode;
    let cachevcode = await this.cacheManager["VCodeCache"].getCache(mobile, 60)
    if (vcode != cachevcode.vcode) {
      return null;
    } else {
      //检查是否在库里存在
      //appkey--company_id---需要控制器基类里设置到p对象里
      let user = await this.cacheManager["UserCache"].cache(mobile)
      if (user) {
        let roleids = user.Roles.map(item => {
          return item.id
        })
        let auths = await this.authS.findAuthsByRole(roleids)
        user["access"] = auths

        //生成token
        let token = await this.cmakejwt(user.jwtkey, user.jwtsecret, null);
        rtn.token = token;
        rtn.user = user;
        return rtn;
      } else {
        //先按照用户名查续身份信息，获取key,secret,
        let regrtn = await this.pmregister({ userName: mobile, nickName: mobile, rolecodes: p.rolecodes, company_id: p.company_id, app_id: p.app_id });
        let token = await this.cmakejwt(regrtn.user.jwtkey, regrtn.user.jwtsecret, null);
        // rtn.token = token;
        // rtn.user = u;

        let userfind = await this.cacheManager["UserCache"].cache(mobile)
        let roleids = userfind.Roles.map(item => {
          return item.id
        })
        let auths = await this.authS.findAuthsByRole(roleids)
        userfind["access"] = auths
        regrtn.user = userfind
        regrtn.token = token
        return regrtn;
      }
    }
    //不一致那么就
  }
  //发送手机验证码并缓存
  async sendVCode (p, q, req) {
    let mobile = p.mobile;
    let vcodeobj = await this.cacheManager["VCodeCache"].cache(mobile, null, 60);
    return vcodeobj.vcode;
  }
  async reSendVCode (p, q, req) {
    let mobile = p.mobile;
    await this.cacheManager["VCodeCache"].invalidate(mobile);
    let vcodeobj = await this.cacheManager["VCodeCache"].cache(mobile, null, 60);
    return vcodeobj.vcode;
  }
  //修改中心密码
  async cmodifypwd (uname, newpwd, cmpid) {
    try {
      let rtn = await system.postJsonTypeReq(UserService.consumerUrl(uname), { tags: ["cmp_" + cmpid, "pass_" + newpwd] }, "PATCH")
      console.log(rtn)
      if (rtn.statusCode == 200) {
        return rtn.data;
      }
      return null;
    } catch (e) {
      console.log(e);
      return null;
    }
  }
  //创建统一账号及jwt身份
  async cregister (uname, cmpid, pass, uid) {
    try {
      var rtn2 = null;
      let rtn = await system.postJsonTypeReq(UserService.newConsumerUrl(), { username: uname, custom_id: uid, tags: ["cmp_" + cmpid, "pass_" + pass] })
      console.log(rtn)
      if (rtn.statusCode == 409) {
        throw new Error("已经存在相同的统一账号名称!");
      } else {
        //创建身份
        rtn2 = await system.post3wFormTypeReq(UserService.newJwtCredUrl(uname))
      }
      if (rtn.statusCode == 201 && rtn2.statusCode == 201) {
        return rtn2.data;
      }
      return null;
    } catch (e) {
      console.log(e);
      return null;
    }
  }
  //plkey--对应消费者jwt身份的key,插件解码token后，获取iss-key,查询出身份，利用
  //身份中的secret验证签名
  async jwtsign (plkey, secretstr, opts) {
    let promise = new Promise(function (resv, rej) {
      jwt.sign({ exp: Math.floor(Date.now() / 1000) + (60 * 60), iss: plkey }, secretstr, opts, function (err, rtn) {
        if (err) {
          rej(err);
        } else {
          resv(rtn);
        }
      });
    });
    return promise;
  }
  //只要登录 生成新的访问jwttoken
  async cmakejwt (key, secret, opts) {
    var token = await this.jwtsign(key, secret, opts);
    return token;
  }

  //删除统一账号
  async cunregister (uname) {
    try {
      let rtn = await system.delReq(UserService.consumerUrl(uname))
      if (rtn.statusCode == 204) {
        return {};
      }
      return null;
    } catch (e) {
      return null;
    }
  }


  //登录统一账号
  async clogin (uname) {
    //检查是否存在重名

  }
  //按用户名查询统一用户
  async findCUser (uname) {

  }
  async resetPassword (uname, pwd) {
    let inpassword = this.getEncryptStr(pwd);
    var self = this;
    return this.db.transaction(async function (t) {
      let up = await self.dao.updateByWhere({ password: inpassword }, { userName: uname }, t);
      //令缓存失效
      await self.cacheManager["UserCache"].invalidate(uname);
      let cacheUser = await self.cacheManager["UserCache"].cache(uname);
      //修改认证中心的tag密码
      let modi = await self.cmodifypwd(uname, inpassword, cacheUser.company.id)
      if (!modi) {
        throw new Error("修改中心密码出错")
      }

      return cacheUser;
    });
  }
  //修改
  async update (qobj, tm = null) {
    var self = this;
    return this.db.transaction(async function (t) {
      delete qobj['company_id']
      let up = await self.dao.update(qobj, t);
      //令缓存失效
      await self.cacheManager["UserCache"].invalidate(qobj.userName);
      let cacheUser = await self.cacheManager["UserCache"].cache(qobj.userName);
      return cacheUser;
    });

  }
  //选择业务员为商机
  //按照客户电话，建立和业务员的映射关系
  //如果已经分配过，那么优先分配
  /**
   * 
   * @param {*} clientMobile 客户电话
   * @param {*} spName 服务商名称
   * @param {*} productCatName 产品类型名称
   * @param {*} regionName 区域
   */
  async getBizUserForBizChance (clientMobile, spName, productCatName, regionName) {
    var self = this
    clientMobile = clientMobile + "_" + spName + "_" + regionName + "_" + productCatName
    //按照服务商名字查询到公司，按照公司查询出users,条件是可以接受派单任务，并且技能标签含有，产品类别名称
    return this.db.transaction(async function (t) {
      //先检查缓存是否存在bizuser
      var resultcache = await self.cacheManager["ClientBindBizUserCache"].getCache(clientMobile)
      let isGoExec = false
      if (!resultcache) {
        isGoExec = true
      } else {
        let uname = resultcache.userName
        let ucache = await self.cacheManager["UserCache"].cache(uname)
        if (!ucache.isAllocated) {//解决修改为不接单
          isGoExec = true
          await self.cacheManager["ClientBindBizUserCache"].invalidate(clientMobile)
        }
      }
      if (isGoExec) {
        let companyFind = await self.companyDao.model.findOne({
          where: { name: spName }, include: [
            {
              model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags', 'regiontags'], raw: true
            }
          ], excludes: ['orgJson'], transaction: t
        });
        console.log(companyFind)
        let users = companyFind.us
        let cansels = users.filter(u => {
          if (regionName && regionName != "" && u.regiontags) {
            if (u.isAllocated && u.isSalesman && u.skilltags.indexOf(productCatName) >= 0 && u.regiontags.indexOf(regionName) >= 0) {
              return true
            } else {
              return false
            }
          } else {
            if (u.isAllocated && u.isSalesman && u.isAllArea && u.skilltags.indexOf(productCatName) >= 0) {
              return true
            } else {
              return false
            }
          }

        })
        let lngth = cansels.length
        if (lngth > 0) {
          let randindex = Math.floor(Math.random() * lngth)
          let selresult = cansels[randindex]
          //添加到缓存，按照客户电话key--缓存到业务员的对象
          let tmp = {
            userId: selresult.id,
            userName: selresult.userName,
            mobile: selresult.mobile,
            opath: selresult.opath,
            compId: companyFind.id
          }
          await self.cacheManager["ClientBindBizUserCache"].cache(clientMobile, tmp)
          return tmp
        } else {
          return null
        }

      } else {
        if (resultcache) {//不继续，直接返回缓存
          return resultcache
        } else {
          return null
        }
      }

    })
  }
  /**
   * 
   * @param {*} clientMobile 客户电话
   * @param {*} spName 服务商名称
   * @param {*} productCatName 产品类型名称
   * @param {*} skucode 最小销售货品编码，来自渠道上架的码
   * @param {*} regionName 区域
   */
  async getBizUserForDelivery (xclientMobile, spName, productCatName, skucode, regionName) {
    let clientMobile = 'fordeliver' + xclientMobile + "_" + spName + "_" + regionName + "_" + productCatName
    var self = this
    //按照服务商名字查询到公司，按照公司查询出users,条件是可以接受派单任务，并且技能标签含有，产品类别名称
    return this.db.transaction(async function (t) {
      //按照产品简码，查询服务成本
      let productpricetmp = await self.db.models.productprice.findOne({
        where: { skucode: skucode },
        include: [
          { model: self.db.models.productcost, as: "costs", attributes: ['id', 'expensetype', 'costamount'] }
        ],
        transaction: t
      }
      )
      let serviceCost = productpricetmp.costs.filter(c => {
        if (c.expensetype == "service") {
          return true
        }
      })
      let costAmount = 0
      //获取服务费成本
      if (serviceCost.length > 0) {
        costAmount = serviceCost[0].costamount
      }

      //先检查缓存是否存在bizuser todo key再加个字母d
      var resultcache = await self.cacheManager["ClientBindBizUserCache"].getCache(clientMobile)
      let isGoExec = false
      if (!resultcache) {
        isGoExec = true
      } else {
        let uname = resultcache.userName
        let ucache = await self.cacheManager["UserCache"].cache(uname)
        if (!ucache.isAllocated) {//解决修改为不接单
          isGoExec = true
          await self.cacheManager["ClientBindBizUserCache"].invalidate(clientMobile)
        }
      }
      if (isGoExec) {
        let companyFind = await self.companyDao.model.findOne({
          where: { name: spName }, include: [
            {
              model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags'], raw: true
            }
          ], excludes: ['orgJson'], transaction: t
        });
        let users = companyFind.us
        let cansels = users.filter(u => {
          if (regionName && regionName != "" && u.regiontags) {
            if (u.isAllocated && u.isDelivery && u.skilltags.indexOf(productCatName) >= 0 && u.regiontags.indexOf(regionName) >= 0) {
              return true
            } else {
              return false
            }
          } else {
            if (u.isAllocated && u.isDelivery && u.isAllArea && u.skilltags.indexOf(productCatName) >= 0) {
              return true
            } else {
              return false
            }
          }
        })
        let lngth = cansels.length
        if (lngth > 0) {
          let randindex = Math.floor(Math.random() * lngth)
          let selresult = cansels[randindex]
          //添加到缓存，按照客户电话key--缓存到业务员的对象
          let tmp = {
            userId: selresult.id,
            userName: selresult.userName,
            mobile: selresult.mobile,
            opath: selresult.opath,
            cost: costAmount,
            compId: companyFind.id
          }
          await self.cacheManager["ClientBindBizUserCache"].cache(clientMobile, tmp)
          return tmp
        } else {
          return null
        }

      } else {
        if (resultcache) {//不继续，直接返回缓存
          resultcache["cost"] = costAmount
          return resultcache
        } else {
          return null
        }
      }
    })
  }

  /**
   * 阿里交付单分配规则(交付单处理业务员和交付员不是一个同一人)
   * @param {*} xclientMobile 客户电话
   * @param {*} spName 服务商名称
   * @param {*} productCatName 产品类型名称
   * @param {*} skucode 最小销售货品编码，来自渠道上架的码
   * @param {*} regionName 区域
   */
  async getBizUserForAliDelivery (xclientMobile, spName, productCatName, skucode, regionName) {
    let clientMobile = 'fordeliver' + xclientMobile + "_" + spName + "_" + regionName
    let self = this
    //按照服务商名字查询到公司，按照公司查询出users,条件是可以接受派单任务，并且技能标签含有，产品类别名称
    return this.db.transaction(async function (t) {
      //按照产品简码，查询服务成本
      let productpricetmp = await self.db.models.productprice.findOne({
        where: { skucode: skucode },
        include: [
          { model: self.db.models.productcost, as: "costs", attributes: ['id', 'expensetype', 'costamount'] }
        ],
        transaction: t
      }
      )
      let serviceCost = productpricetmp.costs.filter(c => {
        if (c.expensetype == "service") {
          return true
        }
      })
      let costAmount = 0
      //获取服务费成本
      if (serviceCost.length > 0) {
        costAmount = serviceCost[0].costamount
      }

      //先检查缓存是否存在bizuser
      let resultcache = await self.cacheManager["DeliveryBizUserCache"].getCache(clientMobile)
      let isGoExec = false
      if (!resultcache) {
        isGoExec = true
      } else {
        let uname = resultcache.userName
        let ucache = await self.cacheManager["UserCache"].cache(uname)
        if (!ucache.isAllocated) {//解决修改为不接单
          isGoExec = true
          await self.cacheManager["DeliveryBizUserCache"].invalidate(clientMobile)
        }
      }
      //TODO 查询数据库user表来获取交付员信息 需要根据是否是"交付员"字段筛选(派单规则是将交付单派给交付员)
      if (isGoExec) {
        let companyFind = await self.companyDao.model.findOne({
          where: { name: spName }, include: [
            {
              model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags'], raw: true
            }
          ], excludes: ['orgJson'], transaction: t
        });
        let users = companyFind.us
        let cansels = users.filter(u => {
          if (regionName && regionName != "" && u.regiontags) {
            if (u.isAllocated && u.isDelivery && u.skilltags.indexOf(productCatName) >= 0 && u.regiontags.indexOf(regionName) >= 0) {
              return true
            } else {
              return false
            }
          } else {
            if (u.isAllocated && u.isDelivery && u.isAllArea && u.skilltags.indexOf(productCatName) >= 0) {
              return true
            } else {
              return false
            }
          }
        })
        let lngth = cansels.length
        //TODO 分配规则,需要改成循环分配
        if (lngth > 0) {
          let randindex = Math.floor(Math.random() * lngth)
          let selresult = cansels[randindex]
          //添加到缓存，按照客户电话key--缓存到业务员的对象
          let tmp = {
            userId: selresult.id,
            userName: selresult.userName,
            mobile: selresult.mobile,
            opath: selresult.opath,
            cost: costAmount,
            compId: companyFind.id
          }
          await self.cacheManager["DeliveryBizUserCache"].cache(clientMobile, tmp)
          return tmp
        } else {
          return null
        }

      } else {
        if (resultcache) {//不继续，直接返回缓存
          resultcache["cost"] = costAmount
          return resultcache
        } else {
          return null
        }
      }
    })
  }
}
module.exports = UserService;

// let userS=new UserService()
// userS.getBizUserForBizChance("13381139519",'好生日','工商注册').then(rtn=>{
//   console.log(rtn)
// })