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

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.jthinking.common.util.ip.IPInfo;
import com.jthinking.common.util.ip.IPInfoUtils;
import org.apache.hc.core5.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.http.common.HttpRequest;
import org.tio.http.server.annotation.RequestPath;
import org.tio.jfinal.kit.Kv;
import org.tio.jfinal.kit.Ret;
import org.tio.sitexxx.im.server.handler.wx.WxChatApi;
import org.tio.sitexxx.im.server.handler.wx.WxSynApi;
import org.tio.sitexxx.server.controller.base.sms.SmsController;
import org.tio.sitexxx.server.utils.GeneratorUtil;
import org.tio.sitexxx.server.utils.WebUtils;
import org.tio.sitexxx.service.api.sms.BaseSmsVo;
import org.tio.sitexxx.service.model.main.IpInfo;
import org.tio.sitexxx.service.model.main.User;
import org.tio.sitexxx.service.model.main.UserTask;
import org.tio.sitexxx.service.model.main.WxChatItems;
import org.tio.sitexxx.service.service.ConfService;
import org.tio.sitexxx.service.service.base.IpInfoService;
import org.tio.sitexxx.service.service.base.RegisterService;
import org.tio.sitexxx.service.service.base.UserService;
import org.tio.sitexxx.service.service.base.sms.SmsService;
import org.tio.sitexxx.service.service.chat.ChatService;
import org.tio.sitexxx.service.service.chat.FriendService;
import org.tio.sitexxx.service.utils.RetUtils;
import org.tio.sitexxx.service.vo.Const;
import org.tio.sitexxx.service.vo.RequestExt;
import org.tio.sitexxx.service.vo.wx.SynRecordVo;
import org.tio.utils.resp.Resp;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Locale;

/**
 *
 *
 */
@RequestPath(value = "/register")
public class RegisterController {

	private static final RegisterService registerService = RegisterService.me;
	private final static FriendService friendService = FriendService.me;
	private static Logger log = LoggerFactory.getLogger(RegisterController.class);

	public static void p2pAfterRegister(User user) {
		Ret slef = ChatService.me.actFdChatItems(user.getId(), user.getId());
		if(slef.isFail()) {
			return;
		}
		WxChatItems selfChatItems = RetUtils.getOkTData(slef, "chat");
		if(WxSynApi.isSynVersion()) {
			WxSynApi.synChatSession(user.getId(), selfChatItems, SynRecordVo.SynType.ADD);
		} else {
			WxChatApi.userActOper(user.getId(),selfChatItems);
		}
	}

	/**
	 * 激活，发送给用户注册邮箱中的带有 authCode 的激活链接指向该 action
	 */
	@RequestPath(value = "/activate")
	public Resp activate(String authCode) {
		Resp resp = registerService.activate(authCode);
		if (resp.isOk()) {
			Kv kv = (Kv) resp.getData();
			User user = (User) kv.get("user");
			p2pAfterRegister(user);
		}
		return resp;
	}

	/**
	 * 邮箱注册
	 * @param user
	 * @param request
	 * @return
	 * @author tanyaowu
	 */
	@RequestPath(value = "/emailRegister")
	public Resp emailRegister(User user, HttpRequest request) throws Exception {
		RequestExt requestExt = WebUtils.getRequestExt(request);
		Resp resp = registerService.emailRegister(user, request.getClientIp(), request.getHttpSession().getId(), requestExt);
		if (resp.isOk()) {
			SmsService.me.delCode(user.getLoginname(), BaseSmsVo.BaseSmsBizType.REGISTER);
			Kv kv = (Kv) resp.getData();
			User reguser = (User) kv.get("user");
			p2pAfterRegister(reguser);
			Integer yangzheng = ConfService.getInt("yanzheng", 0);
			if(yangzheng != 0) {
				Integer userId = reguser.getId();
				user.setId(userId);
				user.update();
				UserService.ME._clearCache(userId);
			}
		}
		return resp;
	}

	/**
	 * @param request
	 * @return
	 * @throws Exception
	 * @author xufei
	 * 2020年12月16日 上午11:13:22
	 */
	@RequestPath(value = "/phoneRegister")
	public Resp phoneRegister(User user, HttpRequest request) throws Exception {
		Integer isShort = ConfService.getInt(Const.ConfMapping.IS_SHORT, 10);
		String phone = user.getLoginname();
		if (!Validator.isMobile(phone)) {
			return RetUtils.getFailResp("请输入正确的手机号");
		}
		Integer isRegister = ConfService.getInt(Const.ConfMapping.IS_REGISTER, 1);
		if(isRegister == 2) {
			return RetUtils.getFailResp("注册已关闭");
		}
		if (StrUtil.isBlank(user.getCode()) && isShort == 1) {
			log.error("验证码不存在");
			return RetUtils.getFailResp("验证码不存在");
		}
		Resp beforeCheck = SmsController.bizPhoneCheck(BaseSmsVo.BaseSmsBizType.REGISTER, user.getLoginname());
		if (!beforeCheck.isOk()) {
			return beforeCheck;
		}
		if(isShort == 1) {
			String code = ConfService.getString(Const.Code.CODE, "");
			if (!TextUtils.isEmpty(code) && !code.equals(user.getCode())) {
				Ret ret = SmsService.me.checkCode(user.getLoginname(), BaseSmsVo.BaseSmsBizType.REGISTER, user.getCode(), null, false);
				if (ret.isFail()) {
					return Resp.fail(RetUtils.getRetMsg(ret));
				}
			}
		}

		String clientIp = request.getClientIp();
		IPInfo ipInfo = IPInfoUtils.getIpInfo(clientIp);
		if (ipInfo.isOverseas()) {
			return Resp.fail("禁止国外ip注册");
		}
		int ipNum = IpInfoService.ME.getByIp(clientIp);
		if(ipNum>3) {
			return Resp.fail("注册失败");
		}

		User first = User.dao.findFirst("select * from user where loginname = ?", user.getLoginname());
		if(first != null) {
			return Resp.fail("号码已经注册");
		}
		String inviteCode = "";
		if (StrUtil.isNotEmpty(user.getInvitecode())) {
			inviteCode = user.getInvitecode().trim().toUpperCase(Locale.ROOT);
		}
		user.setParentInvite(inviteCode);
		user.setInvitecode(GeneratorUtil.generate(8));
		Resp resp = registerService.phoneRegister(user);
		if (resp.isOk()) {
			SmsService.me.delCode(user.getLoginname(), BaseSmsVo.BaseSmsBizType.REGISTER);
			Kv kv = (Kv) resp.getData();
			User reguser = (User) kv.get("user");
			p2pAfterRegister(reguser);

			UserTask userTask = new UserTask();
			userTask.setUid(reguser.getId());
			userTask.setCoin(new BigDecimal(0));
			userTask.setCtime(new Date());
			userTask.setUtime(new Date());
			userTask.setStatus(1);
			userTask.save();

			String keFu = ConfService.getString("keFu", "100000");
			friendService.addCustomer(reguser,Integer.valueOf(keFu));
		}
		return resp;
	}

	/**
	 * api注册逻辑
	 *
	 * avatar:头像-非必传<br>
	 * nick:昵称-必传<br>
	 * loginname:登录名(手机号)-必传<br>
	 * pwd:密码-必传<br>
	 *
	 * @param user
	 * @param request
	 * @return
	 * @throws Exception
	 * @author xufei 2021年1月26日 下午6:35:56
	 */
	@RequestPath(value = "/apiRegister")
	public Resp apiRegister(User user, HttpRequest request,String cardNo) {
		if(user.getLoginname().startsWith("170")||user.getLoginname().startsWith("171")
				||user.getLoginname().startsWith("165")||user.getLoginname().startsWith("162")
				||user.getLoginname().startsWith("167")) {
			return Resp.fail();
		}
		user.setPhone(user.getLoginname());
		completeUser(user, request);
		String pwd = user.getPwd();
		String digestHex = MD5.create().digestHex("${"+user.getLoginname()+"}"+pwd);
		user.setPwd(digestHex);
		user.setPhonepwd(digestHex);
		//默认同意
		user.setAgreement("1");
		Resp resp = registerService.phoneRegister(user);
		Integer userId;
		if (!resp.isOk()) {
			return resp;
		}
		Kv kv = (Kv) resp.getData();
		User reguser = (User) kv.get("user");
		p2pAfterRegister(reguser);
		userId = reguser.getId();
		user.setId(userId);
		user.update();
		UserService.ME._clearCache(userId);;
		return resp;
	}

	/**
	 * 默认注册路径是走的邮箱注册
	 * @param user
	 * @param regType 注册类型：1、邮箱，2、短信
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestPath(value = "/{regType}", forward = "/register/submit")
	public Resp register(User user, Short regType, HttpRequest request) throws Exception {
		if (regType == 1 || regType == 2) {
			completeUser(user, request);
			if (regType == 1) {
				return emailRegister(user, request);
			} else {
				return phoneRegister(user, request);
			}
		}
		return RetUtils.getInvalidResp();
	}

	/**
	 * 用邮箱找回密码（第一步：发地址到邮箱）
	 * @param loginname
	 * @param request
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@RequestPath(value = "/retrievePwd")
	public Resp retrievePwd(String loginname, HttpRequest request) throws Exception {
		RequestExt requestExt = WebUtils.getRequestExt(request);
		return registerService.retrievePwd(loginname, request.getClientIp(), request.getHttpSession().getId(), requestExt);
	}

	/**
	 * 设置新密码（第二步：设置新密码）
	 * @param authCode
	 * @return
	 */
	@RequestPath(value = "/setNewPwd")
	public Resp setNewPwd(HttpRequest request, String authCode, String newpwd) {
		return registerService.setNewPwd(authCode, newpwd);
	}

	private void completeUser(User user, HttpRequest request) {
		IpInfo ipInfo = IpInfoService.ME.save(request.getClientIp());
		user.setIpInfo(ipInfo);
		RequestExt requestExt = WebUtils.getRequestExt(request);
		short deviceType = requestExt.getDeviceType();
		user.setRegistertype(deviceType);
	}
}
