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");
  }

  //登录后的租户创建属于租户的用户
  //需要在控制器里取出公司ID
  //和租户绑定同一家公司
  //按照用户名和密码进行注册
  //控制器端检查用户名和密码非空
  async registerByTantent(p, q) {
    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;
    }
    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是找不到指定的角色，所以是空的

      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 });
      }
      //创建统一账号 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("创建统一账号失败");
      }
    });
  }
  //平台登录
  //登录接口封装kong-url
  //登录路由放行
  //p里面含有appkey,company_id,userName,password
  async pmlogin(p, q, req) {
    var self = this;
    //先要按照用户名，在统一账户中查找存在性
    //如果不存在
    let consumer = await this.cget(UserService.consumerUrl(p.userName));
    if (!consumer.data) {
      return null;
    } else {
      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;
    }
  }
  async jwtsign(plkey, secretstr, opts) {
    let promise = new Promise(function (resv, rej) {
      jwt.sign({ 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) {
      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;
    });

  }
}

module.exports = UserService;
// // (async ()=>{
//    let u=new UserService();
// //   //  let x=await u.cregister("jiangong")
// //   //  console.log(x)
// //   // let x=await u.cunregister("jiangong")
// //   //  console.log(x)
// //   // let t=await u.cmakejwt()
// //   // console.log(t)
//   let ux=u.register({userName:"jiangyong3",password:"123"})
//   console.log(ux);
// // })()