package org.tio.sitexxx.server.controller.base;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdcardUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.hc.core5.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.UploadFile;
import org.tio.http.common.session.HttpSession;
import org.tio.http.server.annotation.RequestPath;
import org.tio.jfinal.kit.Ret;
import org.tio.jfinal.plugin.activerecord.Page;
import org.tio.jfinal.plugin.activerecord.Record;
import org.tio.sitexxx.im.common.ImPacket;
import org.tio.sitexxx.im.common.bs.wx.group.WxGroupOperNtf;
import org.tio.sitexxx.im.server.Ims;
import org.tio.sitexxx.im.server.TioSiteImServerStarter;
import org.tio.sitexxx.im.server.handler.wx.WxChatApi;
import org.tio.sitexxx.im.server.handler.wx.WxSynApi;
import org.tio.sitexxx.im.server.vo.CertifyVo;
import org.tio.sitexxx.server.controller.base.sms.SmsController;
import org.tio.sitexxx.server.utils.WebUtils;
import org.tio.sitexxx.service.Command;
import org.tio.sitexxx.service.ThreadUtil;
import org.tio.sitexxx.service.api.sms.BaseSmsVo;
import org.tio.sitexxx.service.model.main.*;
import org.tio.sitexxx.service.service.ConfService;
import org.tio.sitexxx.service.service.base.IpInfoService;
import org.tio.sitexxx.service.service.base.UserService;
import org.tio.sitexxx.service.service.base.sms.SmsService;
import org.tio.sitexxx.service.service.chat.ChatIndexService;
import org.tio.sitexxx.service.service.chat.ChatService;
import org.tio.sitexxx.service.service.chat.FriendService;
import org.tio.sitexxx.service.utils.*;
import org.tio.sitexxx.service.vo.*;
import org.tio.utils.hutool.StrUtil;
import org.tio.utils.json.Json;
import org.tio.utils.resp.Resp;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tanyaowu
 * 2016年6月29日 下午7:53:59
 */
@RequestPath(value = "/user")
public class UserController {
	private static Logger log = LoggerFactory.getLogger(UserController.class);

	private UserService userService = UserService.ME;

	/**
	 * 搜索用户
	 * @param nick
	 * @param uid
	 * @param loginname
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 * @author tanyaowu
	 * @throws Exception 
	 */
	@RequestPath(value = "/search")
	public Resp search(HttpRequest request, String nick, Integer uid, String loginname, Integer pageNumber, Integer pageSize) throws Exception {
		pageSize = 20;
		if (StrUtil.isNotBlank(nick)) {
			try {
				uid = Integer.parseInt(nick);
			} catch (Exception ignored){
			}
		}
		Page<Record> page = UserService.ME.search(nick, uid, loginname, pageNumber, pageSize);
		return Resp.ok(page);
	}

	/**
	 * 删除用户分组
	 * @param request 请求
	 * @param id 序号
	 * @return
	 */
	@RequestPath(value = "/delUserGroup")
	public Resp delUserGroup(HttpRequest request, Integer id) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		return UserService.ME.delUserGroup(curr, id);
	}

	@RequestPath(value = "/getGoogle")
	public Resp getGoogle(HttpRequest request){
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		Record google = new Record();
		if (Objects.equals(curr.getGoogleStatus(), User.Google.BIND)) {
			google.set("status", User.Google.BIND);
		} else {
			google.set("status", User.Google.UN_BIND);
			String key = GoogleUtils.generateSecretKey();
			curr.setGoogleKey(key);
			curr.update();
			userService.notifyClearCache(curr.getId());
			google.set("key", key);
			String url = GoogleUtils.spawnScanQRString(curr.getLoginname(), key, "谷歌验证码");
			google.set("qr", url);
			String base64 = QRCodeUtil.getBase64QRCode(url);
			google.set("base64", base64);
		}
		return Resp.ok(google);
	}

	@RequestPath(value = "/bindGoogle")
	public Resp bindGoogle(HttpRequest request, String code) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		if (cn.hutool.core.util.StrUtil.isEmpty(code) || !cn.hutool.core.util.StrUtil.isNumeric(code)) {
			return Resp.fail("请输入验证码");
		}
		if (Objects.equals(curr.getGoogleStatus(), User.Google.BIND)) {
			return Resp.ok(User.Google.BIND);
		}
		boolean result = GoogleUtils.check_code(curr.getGoogleKey(), Integer.parseInt(code), System.currentTimeMillis());
		if (!result) {
			return Resp.fail("验证码错误");
		}
		curr.setGoogleStatus(User.Google.BIND);
		curr.update();
		userService.notifyClearCache(curr.getId());
		return Resp.ok(User.Google.BIND);
	}

	@RequestPath(value = "/addExpression")
	public  Resp  addExpression(String url) {
		return Resp.ok();
	}

	@RequestPath(value = "/delExpression")
	public  Resp  delExpression(Long id) {
		return Resp.ok();
	}

	@RequestPath(value = "/expressionList")
	public  Resp  expressionList() {
		return Resp.ok(new ArrayList<>());
	}

	/**
	 * 添加用户分组
	 * @param request 请求
	 * @param name 序号
	 * @param type 类型
	 * @return
	 */
	@RequestPath(value = "/addUserGroup")
	public Resp addUserGroup(HttpRequest request, String name, Integer type) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		return UserService.ME.addUserGroup(curr, name, type);
	}

	/**
	 * 修改分组名称
	 * @param request 请求
	 * @param name 名称
	 * @param gid 序号
	 * @return
	 */
	@RequestPath(value = "/updateUserGroup")
	public Resp updateUserGroup(HttpRequest request, String name, Integer gid) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		if (StrUtil.isEmpty(name)) {
			return Resp.fail("请输入分组名称");
		}
		return UserService.ME.updateUserGroup(gid, name);
	}

	/**
	 * 搜索用户
	 * @param nick
	 * @param pageNumber
	 * @return
	 * @author tanyaowu
	 */
	@RequestPath(value = "/searchNickname")
	public Resp searchNickname(String nick, Integer pageNumber) {
		Integer pageSize = 20;
		Page<Record> page = UserService.ME.searchNickname(nick, pageNumber, pageSize);
		return Resp.ok(page);
	}

	/**
	 * 查询用户信息，主要用于展示给其它人看，所以有的信息是不允许查询出来的
	 * @param uid
	 * @param request
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/info")
	public Resp info(Integer uid, HttpRequest request) throws Exception {
		if (uid == null) {
			return Resp.fail("用户id参数为空");
		}

		Record record = UserService.ME.info(uid);
		if (Objects.equals(User.Status.LOGOUT, record.getShort("status"))) {
			return Resp.fail("该用户已注销");
		}
		User curr = WebUtils.currUser(request);
		if (curr != null) {
			WxChatUserItem fd = ChatIndexService.fdUserIndex(curr.getId(), uid);
			if (ChatService.existFriend(fd)) {
				WxFriend friend = FriendService.me.getFriendInfo(fd.getLinkid());
				if (friend != null) {
					record.set("remarkname", friend.getRemarkname());
				}
				//1:未加入 2:已加入
				record.set("friendStatus", ChatService.checkBlack(0, curr.getId(), uid) ? "1" : "2");
				return Resp.ok(record);
			}
		}
		return Resp.ok(record);
	}

	/**
	 * @param uid
	 * @param request
	 * @return
	 * @author xufei
	 * 2020年10月16日 下午2:01:46
	 */
	@RequestPath(value = "/block")
	public Resp block(Integer uid, HttpRequest request) {
		if (uid == null) {
			return Resp.fail("用户id参数为空");
		}
		User curr = WebUtils.currUser(request);
		WxUserBlackItems items = ChatService.getBlockItems(curr.getId(), uid);
		return Resp.ok(items != null ? Const.YesOrNo.YES : Const.YesOrNo.NO);
	}

	@RequestPath(value = "/getOssConfig")
	public Resp getOssConfig(){
		Map<String, Object> config = new HashMap<>();
		config.put(Const.ModelKey.OSS_KEY, ConfService.getString(Const.ModelKey.OSS_KEY, ""));
		config.put(Const.ModelKey.OSS_APP_ID, ConfService.getString(Const.ModelKey.OSS_APP_ID, ""));
		config.put(Const.ModelKey.OSS_ADDRESS, ConfService.getString(Const.ModelKey.OSS_ADDRESS, ""));
		config.put(Const.ModelKey.OSS_BUCKET, ConfService.getString(Const.ModelKey.OSS_BUCKET, ""));
		config.put(Const.ModelKey.OSS_IS_OSS, ConfService.getString(Const.ModelKey.OSS_IS_OSS, ""));
		return Resp.ok(config);
	}

	/**
	 * 获取当前用户
	 * @param request
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/curr")
	public Resp curr(HttpRequest request) throws Exception {
		User user = WebUtils.currUser(request);
		if (user != null) {
			user.setGoogleKey("");
			if (user.getRoles() == null || user.getRoles().size() == 0) {
				List<Short> role = new ArrayList<>();
				role.add((short) 2);
				user.setRoles(role);
			}
			return Resp.ok(user);
		} else {
			return Resp.fail("未登录");
		}
	}

	/**
	 * 绑定邀请码
	 * @param request 请求
	 * @param code 邀请码
	 * @throws Exception
	 */
	@RequestPath(value = "/bindCode")
	public Resp bindCode(HttpRequest request, String code) {
		if (StrUtil.isEmpty(code)) {
			return Resp.fail("邀请码为空");
		}
		String newCode = code.trim().toUpperCase(Locale.ROOT);
		User user = WebUtils.currUser(request);
		if (user == null) {
			return Resp.fail("未登录");
		}
		if (!StrUtil.isEmpty(user.getParentInvite())) {
			return Resp.fail("邀请码已绑定");
		}
		User manager = User.dao.findFirst("select * from user where invitecode = ? COLLATE utf8mb4_bin", newCode);
		if (manager == null) {
			return Resp.fail("邀请码无效");
		}
		newCode = newCode.trim();
		user.setParentInvite(newCode);
		user.update();
		UserService.ME.notifyClearCache(user.getId());
		return Resp.ok("绑定成功");
	}

	@RequestPath(value = "/push")
	public Resp push(String type, String token, String iosToken, HttpRequest request) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.ok();
		}
		if (cn.hutool.core.util.StrUtil.isEmpty(type) || cn.hutool.core.util.StrUtil.isEmpty(token)) {
			return Resp.fail("参数为空");
		}
		UserService.ME.updatePush(curr.getId(), type, token, iosToken);
		return Resp.ok();
	}

	/**
	 * 根据token，获取用户ID（此处的token其实就是sessionId）
	 * @param request
	 * @param token
	 * @return
	 * @throws Exception
	 * @author: tanyaowu
	 */
	@RequestPath(value = "/byToken")
	public Resp byToken(HttpRequest request, String token) {
		HttpSession httpSession = request.httpConfig.getHttpSession(token);

		if (httpSession != null) {
			SessionExt sessionExt = httpSession.getAttribute(SessionKey.SESSION_EXT, SessionExt.class);
			Integer userid = sessionExt.getUid();
			if (userid != null) {
				return Resp.ok(userid);
			} else {
				log.info("{} session中并未绑定userid", request.getChannelContext());
			}
		} else {
			log.info("{} 不能根据sessionId[{}]找到session对象", request.getChannelContext(), token);
		}
		return Resp.fail();
	}

	/**
	 * 
	 * @param request
	 * @param x userid
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/by")
	public Resp by(HttpRequest request, Integer x) {
		if (x == null) {
			Tio.remove(request.getChannelContext(), "非法请求");
			return null;
		}
		SimpleUser simpleUser = SimpleUser.fromUid(x);
		Resp resp;
		if (simpleUser != null) {
			resp = Resp.ok(simpleUser);
		} else {
			resp = Resp.fail("can not found the userid");
		}
		return resp;
	}

	/**
	 * 实名
	 */
	@RequestPath(value = "/certify")
	public Resp certify(HttpRequest request, CertifyVo data) {
		try {
			User curr = WebUtils.currUser(request);
			if (curr == null) {
				return Resp.fail("未登录");
			}
			if (Objects.equals(curr.getRealnameflag(), Const.YesOrNo.YES)) {
				return Resp.fail("用户已实名");
			}
			String realName = data.getRealName();
			String idCard = data.getIdCard();
			if (StrUtil.isEmpty(realName) || StrUtil.isEmpty(idCard)) {
				return Resp.fail("请输入姓名和身份证");
			}
			Boolean isExits = UserService.ME.selectByCard(idCard);
			if(isExits) {
				return Resp.fail("你的实名无法通过  当前身份证已实名");
			}
			if (!IdcardUtil.isValidCard(idCard) || !Validator.isChinese(realName)) {
				return Resp.fail("实名信息错误");
			}
			User user = new User();
			user.setId(curr.getId());
			user.setRealnameflag((short) 1);
			user.setIdCard(idCard);
			user.setRealName(realName);
			user.update();

			HashMap<String,Object> map = new HashMap<>();
			map.put("isCertify", true);
			map.put("realName", CommonUtils.maskNameRegex(realName));
			map.put("idCard", CommonUtils.maskIdCardRegex(idCard));

			UserService.ME._clearCache(curr.getId());
			return Resp.ok(map);
		} catch (Exception e){
			e.printStackTrace();
			return Resp.fail("系统错误");
		}
	}

	/**
	 * 实名
	 */
	@RequestPath(value = "/getCertify")
	public Resp getCertify(HttpRequest request) {
		try {
			User curr = WebUtils.currUser(request);
			if (curr == null) {
				return Resp.fail("未登录");
			}
			String realName = curr.getRealName();
			String idCard = curr.getIdCard();
			HashMap<String,Object> map = new HashMap<>();
			map.put("isCertify", Objects.equals(curr.getRealnameflag(), Const.YesOrNo.YES));
			map.put("realName", CommonUtils.maskNameRegex(realName));
			map.put("idCard", CommonUtils.maskIdCardRegex(idCard));
			return Resp.ok(map);
		} catch (Exception e){
			e.printStackTrace();
			return Resp.fail("系统错误");
		}
	}

	/**
	 * 
	 * @param userAddress
	 * @param request
	 * @return
	 * @throws Exception
	 * 
	 */
	@RequestPath(value = "/updateAds")
	public Resp updateAds(UserAddress userAddress, HttpRequest request) {
		User user = WebUtils.currUser(request);
		if (user == null) {
			return Resp.fail("未登录");
		}
		Ret ret = userService.updateUserAddress(user.getId(), userAddress);
		if (ret.isOk()) {
			return Resp.ok().data(ret.get("data"));
		} else {
			return Resp.fail(ret.getStr("msg"));
		}
	}
	
	/*********************************************begin- 登录注册相关***************************************************************/
	
	/**
	 * 修改密码
	 * @param request
	 * @param initPwd
	 * @param newPwd
	 * @return
	 * @author xufei
	 * 2022年5月10日 下午12:02:54
	 */
	@RequestPath(value = "/updatePwd")
	public Resp updatePwd(HttpRequest request, String initPwd, String newPwd) {
		if (StrUtil.isBlank(initPwd)) {
			return Resp.fail("原密码不允许为空");
		}
		if (StrUtil.isBlank(newPwd)) {
			return Resp.fail("新密码不允许为空");
		}
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		return userService.updatePwd(curr, initPwd, newPwd);
	}

	/**
	 * 检查密码
	 */
	@RequestPath(value = "/checkPwd")
	public Resp checkPwd(HttpRequest request, String pwd) {
		if (StrUtil.isBlank(pwd)) {
			return Resp.fail("密码不允许为空");
		}
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("未登录");
		}
		return userService.checkPwd(curr, pwd);
	}

	/**
	 * 找回密码前置
	 * 没有邮箱账号后，可以废除该功能，2022年5月后正式废除
	 * @param phone
	 * @param code
	 * @return
	 * @author xufei
	 * 2020年12月16日 下午5:53:11
	 * @throws Exception 
	 */
	@Deprecated
	@RequestPath(value = "/resetPwdBefore")
	public Resp resetPwdBefore(String phone, String code) throws Exception {
		if (StrUtil.isBlank(phone) || StrUtil.isBlank(code)) {
			return RetUtils.getInvalidResp();
		}
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.PWD_BACK, phone);
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		Ret ret = SmsService.me.checkCode(phone, BaseSmsVo.BaseSmsBizType.PWD_BACK, code, null, false);
		if (ret.isFail()) {
			return Resp.fail(RetUtils.getRetMsg(ret));
		}
		User user = userService.getByPhone(phone, null);
		if (user == null) {
			return Resp.fail("用户不存在");
		}
		Map<String, String> login = new HashMap<>();
		login.put("email", user.getEmail());
		login.put("phone", user.getPhone());
		return Resp.ok(login);
	}

	/**
	 * 找回密码
	 * @param phone
	 * @param code
	 * @param emailpwd 没有邮箱账号时，该值可以忽略
	 * @param phonepwd
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年12月16日 下午6:00:46
	 */
	@RequestPath(value = "/resetPwd")
	public Resp resetPwd(String phone, String code, String phonepwd, String emailpwd) throws Exception {
		if (StrUtil.isBlank(phone) || StrUtil.isBlank(code)) {
			return RetUtils.getInvalidResp();
		}
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.PWD_BACK, phone);
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		Ret ret = SmsService.me.checkCode(phone, BaseSmsVo.BaseSmsBizType.PWD_BACK, code, null, false);
		if (ret.isFail()) {
			return Resp.fail(RetUtils.getRetMsg(ret));
		}
		User user = userService.getByPhone(phone, null);
		if (user == null) {
			return Resp.fail("用户不存在");
		}
		Resp resp = userService.resetPwd(user, phonepwd, emailpwd);
		if (resp.isOk()) {
			SmsService.me.delCode(phone, BaseSmsVo.BaseSmsBizType.PWD_BACK);
		}
		return resp;
	}
	
	/**
	 * 注销检测
	 * @param uid
	 * @param request
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2021年4月8日 下午2:54:04
	 */
	@RequestPath(value = "/logoutcheck")
	public Resp logoutCheck(Integer uid, HttpRequest request) {
		User user = WebUtils.currUser(request);
		if (!Objects.equals(uid, user.getId())) {
			return Resp.fail("登录已失效，请刷新");
		}
		if (!Objects.equals(User.Status.NORMAL, user.getStatus())) {
			return Resp.fail("注销申请失败，请确认账号状态");
		}
		return Resp.ok();
	}
	
	/**
	 * 注销
	 * @param uid
	 * @param request
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2021年2月26日 下午4:51:56
	 */
	@RequestPath(value = "/logout")
	public Resp logout(Integer uid, String code, HttpRequest request) throws Exception {
		User user = WebUtils.currUser(request);
		if (!Objects.equals(uid, user.getId())) {
			return Resp.fail("登录已失效，请刷新");
		}
		Ret smsRet = SmsService.me.checkCode(user.getPhone(), BaseSmsVo.BaseSmsBizType.LOGOUT, code, null, false);
		if (smsRet.isFail()) {
			return Resp.fail(RetUtils.getRetMsg(smsRet));
		}
		if (!Objects.equals(User.Status.NORMAL, user.getStatus())) {
			return Resp.fail("注销申请失败，请确认账号状态");
		}
		String ip = request.getClientIp();
		IpInfo ipinfo = IpInfoService.ME.save(ip);
		Ret ret = userService.logout(user, ipinfo.getId());
		if (ret.isFail()) {
			log.error(RetUtils.getRetMsg(ret));
			return Resp.fail().msg(RetUtils.getRetMsg(ret));
		}
		Map<String, List<Ret>> retMap = RetUtils.getOkTData(ret);
		List<Ret> friendList = retMap.get("friend");
		List<Ret> groupList = retMap.get("group");
		//消息触发
		ThreadUtil.getBsExecutor().execute(() -> {
			try {
				Integer uid1 = user.getId();
				for (Ret ret1 : groupList) {
					Long groupid = RetUtils.getOkTData(ret1, "groupid");
					Tio.unbindGroup(TioSiteImServerStarter.tioServerConfigWs, user.getId() + "", groupid + "");
					//自己退群操作
					WxGroupOperNtf leaveNtf = new WxGroupOperNtf();
					leaveNtf.setC("自动退群");
					leaveNtf.setMid(null);
					leaveNtf.setT(System.currentTimeMillis());
					leaveNtf.setUid(uid1);
					leaveNtf.setG(groupid);
					leaveNtf.setChatlinkid(-groupid);
					leaveNtf.setOper(Const.WxGroupOper.LEAVE_GROUP);
					ImPacket imPacket = new ImPacket(Command.WxGroupOperNtf, Json.toJson(leaveNtf));
					Ims.sendToUser(uid1, imPacket);
					WxChatGroupItem newowner = RetUtils.getOkTData(ret1, "owner");
					WxChatGroupItem leave = RetUtils.getOkTData(ret1, "leave");
					WxChatApi.leaveGroup(user, leave, newowner, false);
				}
			} catch (Exception e) {
				log.error("", e);
			}
		});
		ThreadUtil.getBsExecutor().execute(() -> {
			try {
				Integer uid12 = user.getId();
				for (Ret ret12 : friendList) {
					Long chatlinkid = RetUtils.getOkTData(ret12, "chatlinkid");
					Long tochatlinkid = RetUtils.getOkTData(ret12, "tochatlinkid");
					Integer touid = RetUtils.getOkTData(ret12, "touid");
					if (WxSynApi.isSynVersion()) {
						WxSynApi.synFriendDel(uid12, touid, chatlinkid, tochatlinkid, RetUtils.getOkTData(ret12, "fid"));
					} else {
						if (chatlinkid != null) {
							WxChatApi.userChatOper(uid12, chatlinkid, Const.WxUserOper.DEL_FRIEND, "删除好友", "", null);
						}
						if (tochatlinkid != null) {
							WxChatApi.userChatOper(touid, tochatlinkid, Const.WxUserOper.TO_DEL_FRIEND, "被删除好友", "", null);
						}
						WxChatApi.friendChangeDelNtf(uid12, RetUtils.getOkTData(ret12, "fid"));
					}
				}
			} catch (Exception e) {
				log.error("", e);
			}
		});
		SmsService.me.delCode(user.getPhone(), BaseSmsVo.BaseSmsBizType.LOGOUT);
		return Resp.ok();
	}

	/**
	 * @param request
	 * @param phone
	 * @param code
	 * @param emailpwd
	 * @param phonepwd
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年12月16日 下午6:11:21
	 */
	@RequestPath(value = "/bindnewphone")
	public Resp bindnewphone(HttpRequest request, String phone, String code, String phonepwd, String emailpwd) throws Exception {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		String oldPhone = curr.getPhone();
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.BIND_NEW_PHONE, phone);
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		Ret ret = SmsService.me.checkCode(phone, BaseSmsVo.BaseSmsBizType.BIND_NEW_PHONE, code, null, false);
		if (ret.isFail()) {
			return Resp.fail().msg(RetUtils.getRetMsg(ret));
		}
		if (Objects.equals(curr.getEmailbindflag(), Const.YesOrNo.YES)) {
			if (StrUtil.isBlank(emailpwd)) {
				return Resp.fail().msg("请输入密码");
			}
			if (!emailpwd.equals(curr.getEmailpwd())) {
				return Resp.fail().msg("密码不正确");
			}
		}
		if (StrUtil.isBlank(phonepwd)) {
			phonepwd = "";
		}
		//修改用戶绑定手机号
		Resp resp = userService.bindNewPhone(curr, phone, phonepwd, emailpwd);
		if (resp.isOk()) {
			SmsService.me.delCode(phone, BaseSmsVo.BaseSmsBizType.BIND_NEW_PHONE);
			SmsService.me.delCode(oldPhone, BaseSmsVo.BaseSmsBizType.OLD_PHONE_CHECK);
		}
		return resp;
	}
	
	/**
	 * @param request
	 * @param phone
	 * @param code
	 * @param emailpwd
	 * @param phonepwd
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年12月16日 下午4:37:14
	 */
	@RequestPath(value = "/bindphone")
	public Resp bindphone(HttpRequest request, String phone, String code, String emailpwd, String phonepwd) throws Exception {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.BIND_PHONE, phone);
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		Ret ret = SmsService.me.checkCode(phone, BaseSmsVo.BaseSmsBizType.BIND_PHONE, code, null, false);
		if (ret.isFail()) {
			return Resp.fail().msg(RetUtils.getRetMsg(ret));
		}
		if (Objects.equals(curr.getEmailbindflag(), Const.YesOrNo.YES)) {
			if (StrUtil.isBlank(emailpwd)) {
				return Resp.fail().msg("请输入密码");
			}
			if (!emailpwd.equals(curr.getEmailpwd())) {
				return Resp.fail().msg("密码不正确");
			}
		}
		if (StrUtil.isBlank(phonepwd)) {
			phonepwd = "";
		}
		//修改用戶绑定手机号
		Resp resp = userService.bindPhone(curr, phone, phonepwd, emailpwd);
		if (resp.isOk()) {
			SmsService.me.delCode(phone, BaseSmsVo.BaseSmsBizType.BIND_PHONE);
		}
		return resp;
	}
	/*********************************************end - 登录注册相关***************************************************************/
	
	
	
	/*********************************************begin - 修改用户信息相关***************************************************************/
	/**
	 * 修改昵称
	 * @param nick
	 * @param request
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/updateNick")
	public Resp updateNick(HttpRequest request, String nick) {
		User curr = WebUtils.currUser(request);
		if (StrUtil.isBlank(nick)) {
			return RetUtils.getInvalidResp();
		}
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		//重置头像
		Resp resp = userService.updateNick(curr, nick);
		User user = UserService.ME.getById(curr.getId());
		//清空缓存
		ThreadUtil.getBsExecutor().execute(() -> {
			try {
				WxChatApi.synUserInfoToSelfAllInfo(curr.getId(), Const.UserToImSynType.USER_ALL, user);
			} catch (Exception e) {
				log.error("", e);
			}
		});
		return resp;
	}

	/**
	 * 修改头像
	 * @param request
	 * @param uploadFile
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/updateAvatar")
	public Resp updateAvatar(HttpRequest request, UploadFile uploadFile, String url, String fileName, Long width, Long height) throws Exception {
		if (uploadFile == null && url == null) {
			return Resp.fail("上传信息为空");
		}
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail("您尚未登录或登录超时").code(AppCode.ForbidOper.NOTLOGIN);
		}
		Integer uid = curr.getId();
		Img img;
		if (TextUtils.isBlank(url)) {
			int isOss = ConfService.getInt(Const.OssConfig.IS_OSS, 1);
			if (uploadFile == null) {
				return Resp.fail("上传信息为空");
			}
			if (isOss == 1) {
				img = processUploadedImg(uid,  uploadFile);
			}  else {
				img = processOssImg(uploadFile);
			}
		} else {
			img = new Img();
			img.setCoverheight(height.intValue());
			img.setCoversize(1024);
			img.setCoverwidth(width.intValue());
			img.setCoverurl(url);
			img.setUrl(url);
			img.setUid(uid);
			img.setFilename(fileName);
			img.setHeight(height.intValue());
			img.setWidth(width.intValue());
			img.setSize(1024L);
			img.setTitle(fileName);
		}

		img.setComefrom(Img.ComeFrom.MODIFY_AVATAR);
		img.setUid(uid);
		img.setStatus((short) 1);
		img.setSession(request.getHttpSession().getId());
		boolean f = img.save();
		if (f) {
			Resp resp = userService.updateAvatar(curr, img.getUrl());
			User sendUser = UserService.ME.getById(curr.getId());
			ThreadUtil.getBsExecutor().execute(() -> {
				try {
					WxChatApi.synUserInfoToSelfAllInfo(curr.getId(), Const.UserToImSynType.AVATAR, sendUser);
				} catch (Exception e) {
					log.error("", e);
				}
			});
			return resp;
		} else {
			return Resp.fail("服务器异常");
		}
	}

	/**
	 * 用户上传的图片-已调整
	 * 可抽象TODO:XUFEI
	 * @param uploadFile
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年2月5日 下午7:44:47
	 */
	private Img processUploadedImg(Integer userId,UploadFile uploadFile) throws Exception {
		byte[] imageBytes = uploadFile.getData();
		BufferedImage bi = ImgUtil.toImage(imageBytes);
		float scale = ImgUtils.calcScaleWithWidth(400, bi);
		return ImgUtils.processImg(Const.UPLOAD_DIR.WX_IMG, userId, uploadFile, scale);
	}

	/**
	 * 用户上传的图片-已调整
	 * 可抽象TODO:XUFEI
	 * @param uploadFile
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年2月5日 下午7:44:47
	 */
	private Img processOssImg(UploadFile uploadFile) {
		byte[] imageBytes = uploadFile.getData();
		String filename = uploadFile.getName();
		OssConfig ossConfig = ConfService.getOssConfig();
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(imageBytes);
		String uploadPath = OssUtils.upload(ossConfig, filename, byteArrayInputStream, "ltimg/", "");

		Img img = new Img();
		img.setFilename(filename);
		img.setTitle(filename);
		img.setCoverurl(uploadPath);
		BufferedImage bi = ImgUtil.toImage(imageBytes);
		img.setWidth(bi.getWidth());
		img.setHeight(bi.getHeight());
		img.setCoverwidth(bi.getWidth());
		img.setCoverheight(bi.getHeight());
		img.setCoversize(uploadFile.getSize());
		img.setSize((long) uploadFile.getSize());
		img.setUrl(uploadPath);
		return img;
	}
	/**
	 * 修改好友验证方式
	 * @param request
	 * @param fdvalidtype
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年3月3日 下午5:22:55
	 */
	@RequestPath(value = "/updatValid")
	public Resp updatValid(HttpRequest request, Short fdvalidtype) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		return userService.updateFdvalidtype(curr, fdvalidtype);
	}

	/**
	 * 消息提醒设置
	 * @param request
	 * @param remindflag
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年3月3日 下午6:20:57
	 */
	@RequestPath(value = "/updatRemind")
	public Resp updatRemind(HttpRequest request, Short remindflag) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		return userService.updateRemind(curr, remindflag);
	}

	/**
	 * 允许别人搜索设置
	 * @param request
	 * @param searchflag
	 * @return
	 * @author xufei
	 * 2020年3月3日 下午6:24:29
	 */
	@RequestPath(value = "/updatSearchFlag")
	public Resp updatSearchFlag(HttpRequest request, Short searchflag) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		return userService.updateSearchFlag(curr, searchflag);
	}

	/**
	 * 修改签名
	 * @param request
	 * @param sign
	 * @return
	 * @author xufei
	 * 2020年3月3日 下午6:35:05
	 */
	@RequestPath(value = "/updatSign")
	public Resp updatSign(HttpRequest request, String sign) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		return userService.updateSign(curr, sign);
	}

	/**
	 * 修改用户
	 * @param request
	 * @param user
	 * @return
	 * @author xufei
	 * 2020年4月23日 上午11:06:17
	 */
	@RequestPath(value = "/updatUser")
	public Resp updatUser(HttpRequest request, User user) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		String nick = user.getNick();
		if (StrUtil.isBlank(user.getAvatar())) {
			user.setAvatar(curr.getAvatar());
		}
		Resp resp = userService.updateUser(curr, user);
		User sendUser = UserService.ME.getById(curr.getId());
		ThreadUtil.getBsExecutor().execute(() -> {
			try {
				WxChatApi.synUserInfoToSelfAllInfo(curr.getId(), Const.UserToImSynType.USER_ALL, sendUser);
			} catch (Exception e) {
				log.error("", e);
			}
		});
		return resp;
	}

	/**
	 * 修改性别
	 * @param request
	 * @param sex
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年3月3日 下午6:35:35
	 */
	@RequestPath(value = "/updatSex")
	public Resp updatSex(HttpRequest request, Short sex) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		if (Objects.equals(sex, Const.UserSex.FEMALE) || Objects.equals(sex, Const.UserSex.MALE) || Objects.equals(sex, Const.UserSex.SECRET)) {
			return userService.updateSex(curr, sex);
		}
		return Resp.fail("无效性别");
	}
	/********************************************* end - 修改用户信息相关***************************************************************/
	
	/********************************************* begin - 废弃 ***************************************************************/
	
	/**
	 * 修改手机号-老版本的修改附属信息的手机号，废除
	 * @param request
	 * @param phone
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年3月3日 下午6:34:22
	 */
	@Deprecated
	@RequestPath(value = "/updatPhone")
	public Resp updatPhone(HttpRequest request, String phone) {
		User curr = WebUtils.currUser(request);
		if (curr == null) {
			return Resp.fail().msg("用户未登录");
		}
		//修改用戶好友验证方式
		return userService.updatePhone(curr, phone);
	}
	
	/**
	 * 手机注册绑定邮箱-废弃
	 * @param phone
	 * @param code
	 * @param emailpwd
	 * @param phonepwd
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年12月24日 下午6:12:58
	 */
	@Deprecated
	@RequestPath(value = "/regbindemail")
	public Resp regbindemail(String phone, String code, String email, String emailpwd, String phonepwd) throws Exception {
		if (StrUtil.isBlank(phonepwd) || StrUtil.isBlank(emailpwd)) {
			return Resp.fail().msg("密码不能为空");
		}
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.REGISTER, phone);
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		Ret ret = SmsService.me.checkCode(phone, BaseSmsVo.BaseSmsBizType.REGISTER, code, null, false);
		if (ret.isFail()) {
			return Resp.fail().msg(RetUtils.getRetMsg(ret));
		}
		User old = userService.getByEmail(email, null);
		if (old == null) {
			return Resp.fail().msg("邮箱未注册");
		}
		if (!old.getEmailpwd().equals(emailpwd)) {
			return Resp.fail().msg("密码不正确");
		}
		//修改用戶绑定手机号
		Resp resp = userService.regbindemail(old, phone, phonepwd, emailpwd);
		if (resp.isOk()) {
			SmsService.me.delCode(phone, BaseSmsVo.BaseSmsBizType.REGISTER);
		}
		return resp;
	}

	@RequestPath(value = "/selectInviteUser")
	public Resp  selectinviteUser(HttpRequest request){
		User curr = WebUtils.currUser(request);
		List<Record> list = UserService.ME.findChild(curr.getId());
		List<Integer> ids=list.stream().map(d ->d.getInt("id")).collect(Collectors.toList());
		List<Record> childlist = UserService.ME.findByPids(ids);
		ArrayList<Object> resultList = new ArrayList<Object>();
		for (Record u : list) {
			JSONObject jsonObject = new JSONObject();
			Integer id = u.getInt("id");
			String nick = u.getStr("nick");
			String avatar = u.getStr("avatar");
			jsonObject.put("id", id);
			jsonObject.put("nick", nick);
			jsonObject.put("avatar", avatar);
			
			List<Record> childList = childlist.stream().filter(item ->{
				Integer pid = item.getInt("pid");
				return pid.equals(id);
			 }).collect(Collectors.toList());
			ArrayList<JSONObject> jsonList = new ArrayList<JSONObject>();
			for (Record s : childList) {
				JSONObject sjson = new JSONObject();
				Integer sid = s.getInt("id");
				String snick = s.getStr("nick");
				String savatar = s.getStr("avatar");
				sjson.put("id", sid);
				sjson.put("nick", snick);
				sjson.put("avatar", savatar);
				jsonList.add(sjson);
			}
			jsonObject.put("children", jsonList);
			
			resultList.add(jsonObject);
		}
		return Resp.ok(resultList);
	}
}
