package com.bcxin.ars.rest.app;

import com.bcxin.ars.dao.sys.MessageLogDao;
import com.bcxin.ars.dto.AjaxResult;
import com.bcxin.ars.dto.UserDto;
import com.bcxin.ars.model.OfflineNotice;
import com.bcxin.ars.model.ThirdAuthorization;
import com.bcxin.ars.model.User;
import com.bcxin.ars.model.task.AppAbout;
import com.bcxin.ars.rest.dto.AppAjaxResult;
import com.bcxin.ars.rest.util.ArsRestUtil;
import com.bcxin.ars.service.LoginLogService;
import com.bcxin.ars.service.SecurityPersonService;
import com.bcxin.ars.service.ThirdAuthorizationService;
import com.bcxin.ars.service.UserService;
import com.bcxin.ars.service.sys.OfflineNoticeService;
import com.bcxin.ars.service.task.AppAboutService;
import com.bcxin.ars.util.JPushUtil;
import com.bcxin.ars.util.Sha1Util;
import com.bcxin.ars.util.StringUtil;
import com.bcxin.ars.util.redis.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("app/user")
public class AppUserController {

	Logger logger = LoggerFactory.getLogger(AppUserController.class);

	@Autowired
	private UserService userService;

	@Autowired
	private ArsRestUtil arsUtil;
	@Autowired
	private MessageLogDao messageLogDao;
	@Autowired
	private RedisUtil redisUtil;

	@Value("${message-code-timeout}")
	private int messageCodeTimeout = 2;

	@Value("${login-timeout}")
	private int loginTimeout = 10;

	@Autowired
	private OfflineNoticeService offlineNoticeService;

	@Autowired
	private LoginLogService loginLogService;

	@Autowired
	private ThirdAuthorizationService thirdAuthorizationService;

	@Autowired
	private AppAboutService appAboutService;

	@Value("${trainURL}")
	private String trainURL;

	@Value("${oldTrainURL}")
	private String oldTrainURL;

	@Value("${BBD_H5_URL}")
	private String bbdH5Url;

	@Autowired
	private SecurityPersonService personService;


	/**
	 * 登录
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping(value = "login", method = RequestMethod.POST)
	public @ResponseBody AppAjaxResult login(AppAjaxResult appResult) throws Exception {
		//切换到SaaS APP屏蔽旧版登陆入口 edit 2019-03-05 subh ,直接返回登陆失败，提示更新app pro start
		AppAjaxResult result = new AppAjaxResult();
		result.setSuccessful(false);
		result.setMsg("因平台全面升级此版本已停止使用，请下载百保盾PRO开启全新体验");
		//切换到SaaS APP屏蔽旧版登陆入口 edit 2019-03-05 subh ,直接返回登陆失败，提示更新app pro end
		return result;
	}

	/**
	 * 保存用户授权
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping("authorization/save")
	public @ResponseBody AppAjaxResult saveAuthorization(AppAjaxResult appResult) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			ThirdAuthorization thirdAuthorization = appResult.getDecodeData(ThirdAuthorization.class);
			thirdAuthorizationService.saveOrUpdate(thirdAuthorization);
			result.setSuccessful(true);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 取消用户授权
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping("authorization/delete")
	public @ResponseBody AppAjaxResult deleteAuthorization(AppAjaxResult appResult) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			ThirdAuthorization thirdAuthorization = appResult.getDecodeData(ThirdAuthorization.class);
			thirdAuthorizationService.delete(thirdAuthorization);
			result.setSuccessful(true);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 忘记密码
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping("forgetPwd")
	public @ResponseBody AppAjaxResult forgetPwd(AppAjaxResult appResult) throws Exception {
		/*AppAjaxResult result = new AppAjaxResult();
		try {
			User loginUser = appResult.getDecodeData(User.class);
			User user = userService.findByUsername(loginUser.getUsername(),null);
			if (user != null) {
				if (user.getRealname().equals(loginUser.getRealname().trim())
						&& user.getPhone().equals(loginUser.getPhone().trim())) {
					int code = MessageUtil.sendMessageCode(loginUser.getPhone(), messageLogDao);
					redisUtil.set(code + "", loginUser.getUsername(), (messageCodeTimeout * 60));
					result.setSuccessful(true);
					result.setMsg("验证码已发送。");
				} else {
					result.setSuccessful(false);
					result.setMsg("用户信息错误。");
				}
			} else {
				result.setSuccessful(false);
				result.setMsg("该用户不存在。");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}*/
		//切换到SaaS APP屏蔽旧版登陆入口 edit 2019-03-05 subh ,直接返回登陆失败，提示更新app pro start
		AppAjaxResult result = new AppAjaxResult();
		result.setSuccessful(false);
		result.setMsg("因平台全面升级此版本已停止使用，请下载百保盾PRO开启全新体验");
		//切换到SaaS APP屏蔽旧版登陆入口 edit 2019-03-05 subh ,直接返回登陆失败，提示更新app pro end
		return result;
	}

	@RequestMapping(value = "verifyMessageCode", method = RequestMethod.POST)
	public @ResponseBody AppAjaxResult verifyMessageCode(AppAjaxResult appResult, HttpServletRequest request)
			throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			User loginUser = appResult.getDecodeData(User.class);
			String un = redisUtil.get(loginUser.getMessageCode());
			if (un != null && un.equals(loginUser.getUsername())) {
				result.setSuccessful(true);
				result.setMsg("短信验证码正确.");
			} else {
				result.setSuccessful(false);
				result.setMsg("短信验证码错误.");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 修改密码
	 * 
	 * @param appResult
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "updatePwd", method = RequestMethod.POST)
	public @ResponseBody AjaxResult updatePwd(AppAjaxResult appResult, HttpServletRequest request) throws Exception {
		AjaxResult result = new AjaxResult();
		try {
			User loginUser = appResult.getDecodeData(User.class);
			logger.info(loginUser.getMessageCode() + "," + loginUser.getUsername());
			String un = redisUtil.get(loginUser.getMessageCode());
			if (un != null && un.equals(loginUser.getUsername())) {
				User user = userService.findByUsername(loginUser.getUsername(),null);
				if (user != null) {
					user.setPassword(Sha1Util.entryptPassword(loginUser.getPassword()));
					user.setUpdateTime(new Date());
					user.setUpdateBy(user.getUsername());
					userService.updatePassword(user);
					result.setSuccessful(true);
				} else {
					result.setSuccessful(false);
					result.setMsg("用户信息错误.");
				}
			} else {
				result.setSuccessful(false);
				result.setMsg("短信验证码错误.");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 完成初始化
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "finishInit", method = RequestMethod.POST)
	public @ResponseBody AppAjaxResult finishInit(HttpServletRequest request) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			User user = arsUtil.getCurrentUser();
			if (user != null) {
				User dbUser = userService.findByUsername(user.getUsername(),user.getPlatform()==null?null:user.getPlatform().toString());
				dbUser.setInit(true);
				userService.saveOrUpdate(dbUser,user.getPlatform()==null?null:user.getPlatform().toString());
				result.setSuccessful(true);
				dbUser.setSessionId(user.getSessionId());
				Subject currentUser = SecurityUtils.getSubject();
				Session session = currentUser.getSession();
				arsUtil.setCurrentUser(dbUser, (int) session.getTimeout());
				result.setEncodeData(dbUser);
			} else {
				result.setSuccessful(false);
				result.setMsg("当前用户信息错误");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 修改密码不需要短信校验
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping(value = "v-1-0-9/updatePwdNoCheckSms", method = RequestMethod.POST)
	public @ResponseBody AjaxResult updatePwdNoCheckSms(AppAjaxResult appResult) throws Exception {
		AjaxResult result = new AjaxResult();
		try {
			UserDto userDto = appResult.getDecodeData(UserDto.class);
			String oldPassword = userDto.getOldPassword();
			String newPassword = userDto.getNewPassword();
			if (StringUtils.isEmpty(oldPassword)) {
				result.setSuccessful(false);
				result.setMsg("旧密码不能为空!");
				return result;
			}
			if (StringUtils.isEmpty(newPassword)) {
				result.setSuccessful(false);
				result.setMsg("新密码不能为空!");
				return result;
			}
			User userLogin = arsUtil.getCurrentUser();
			logger.info(userLogin.getUsername() + "通过App修改密码");
			User user = userService.findById(userLogin.getId());
			if (user != null) {
				if (Sha1Util.validatePassword(oldPassword, user.getPassword())) {
					newPassword = Sha1Util.entryptPassword(newPassword);
					user.setPassword(newPassword);
					user.setUpdateTime(new Date());
					user.setUpdateBy(user.getUsername());
					userService.updatePassword(user);
					result.setSuccessful(true);
					result.setMsg("密码修改成功.");
				} else {
					result.setSuccessful(false);
					result.setMsg("旧密码不正确.");
				}
			} else {
				result.setSuccessful(false);
				result.setMsg("查找不到用户登陆信息.");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 个人中心-设置-关于我们列表
	 * 
	 * @param appResult
	 * @return
	 */
	@RequestMapping(value = "config/about/v-1-0-9/findappaboutlist")
	public @ResponseBody AppAjaxResult findAppAboutList(AppAjaxResult appResult) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			AppAbout appAbout = new AppAbout();
			List<AppAbout> appAboutList = appAboutService.findAppAboutList(appAbout);
			result.setSuccessful(true);
			result.setData(appAboutList);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 个人中心-设置-关于我们详情
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "config/about/v-1-0-9/findappaboutdetail/{id}")
	public @ResponseBody AppAjaxResult findappaboutdetail(@PathVariable("id") Long id) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			AppAbout appAbout = appAboutService.findById(id);
			result.setSuccessful(true);
			result.setData(appAbout);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 修改用户登陆步骤标记
	 * 
	 * @param flag
	 *            登陆步骤：协议1,认证2,重置密码3,初始化信息4
	 * @return
	 */
	@RequestMapping(value = "v-1-0-9/updateflag/{flag}")
	public @ResponseBody AppAjaxResult updateFlag(@PathVariable("flag") String flag) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			if (StringUtils.isEmpty(flag)) {
				result.setSuccessful(false);
				result.setMsg("登陆步骤标识不能为空!");
				return result;
			}
			User user = arsUtil.getCurrentUser();
			if (user != null) {
				User dbUser = userService.findById(user.getId());
				dbUser.setFlag(flag);
				userService.updateFlag(dbUser);
				result.setSuccessful(true);
				dbUser.setSessionId(user.getSessionId());
				Subject currentUser = SecurityUtils.getSubject();
				Session session = currentUser.getSession();
				arsUtil.setCurrentUser(dbUser, (int) session.getTimeout());
				result.setEncodeData(dbUser);
			} else {
				result.setSuccessful(false);
				result.setMsg("获取用户登陆信息失败");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	/**
	 * 修改用户认证标记
	 * 
	 * @param isAuthMark
	 *            跳过认证标识：0未跳过，1跳过
	 * @return
	 */
	@RequestMapping(value = "v-1-0-9/updateauthmark/{isAuthMark}")
	public @ResponseBody AppAjaxResult updateAuthMark(@PathVariable("isAuthMark") Long isAuthMark) throws Exception {
		AppAjaxResult result = new AppAjaxResult();
		try {
			if (isAuthMark == null) {
				result.setSuccessful(false);
				result.setMsg("跳过认证标识不能为空!");
				return result;
			}
			User user = arsUtil.getCurrentUser();
			if (user != null) {
				User dbUser = userService.findById(user.getId());
				dbUser.setAuthMark(isAuthMark == 0 ? false : true);
				userService.updateAuthMark(dbUser);
				result.setSuccessful(true);
				dbUser.setSessionId(user.getSessionId());
				Subject currentUser = SecurityUtils.getSubject();
				Session session = currentUser.getSession();
				arsUtil.setCurrentUser(dbUser, (int) session.getTimeout());
				result.setEncodeData(dbUser);
			} else {
				result.setSuccessful(false);
				result.setMsg("获取用户登陆信息失败");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

	private AppAjaxResult userLogin(User loginUser,HttpServletRequest request) throws Exception{
		AppAjaxResult result = new AppAjaxResult();
		UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUsername(), loginUser.getPassword());
		Subject currentUser = SecurityUtils.getSubject();
		try {
			token.setRememberMe(true);
			try {
				currentUser.login(token);
			} catch (AuthenticationException e) {
				logger.error(e.getMessage(), e);
				result.setSuccessful(false);
				result.setMsg("用户名/密码错误");
				return result;
			}

			// 判断是否登录成功！
			if (currentUser.isAuthenticated()) {
				Session session = currentUser.getSession();
				User user = userService.findByUsername(loginUser.getUsername(),null);
				logger.info("当前登录用户是：" + user.getUsername());
				// UUID uuid = UUID.randomUUID();
				user.setSessionId(session.getId().toString());
				// 培训平台地址
				user.setTrainURL(trainURL);
				// 旧培训平台地址
				user.setOldTrainURL(oldTrainURL);
				// 百保盾H5地址
				user.setBbdH5Url(bbdH5Url);
				arsUtil.setCurrentUser(user, -1000);
				user.setThirdAuthorizationList(thirdAuthorizationService.findByUserIdForApp(user.getId()));
				result.setEncodeData(user);
				result.setSuccessful(true);
				// 如果是在线的话，那么推送下线通知
				if (user.getLoginstate() != null && user.getLoginstate() == 1 && !"".equals(user.getRegistrationID())
						&& user.getRegistrationID() != null
						&& !user.getRegistrationID().equals(loginUser.getRegistrationID() + user.getId())) {
					String registrationID = user.getRegistrationID();
					Map<String, String> map = new HashMap<String, String>();
					map.put("offline", "true");
					map.put("message", "其它设备登陆");
					// 下线通知
					new Thread(() -> { // 异步处理
						try {
							JPushUtil.sendMessage("下线通知！", "其它设备登陆", registrationID, map);
							/***
							 * 保存下线信息
							 */
							OfflineNotice offlineNotice = new OfflineNotice();
							offlineNotice.setUserId(user.getId());
							offlineNotice.setRegistrationID(registrationID);
							offlineNotice = offlineNoticeService.get(offlineNotice);
							if (offlineNotice == null) {
								offlineNotice = new OfflineNotice();
								offlineNotice.setActive(true);
								offlineNotice.setTitle("下线通知");
								offlineNotice.setMessage("其它设备登陆");
								offlineNotice.setCreateTime(new Date());
								offlineNotice.setUpdateTime(new Date());
								offlineNotice.setUserId(user.getId());
								offlineNotice.setUpdateBy(user.getRealname());
								offlineNotice.setRegistrationID(registrationID);
								offlineNoticeService.save(offlineNotice);
							}
						} catch (Exception e) {

						}
					}).start();
				}
				// 更新一下登陆状态
				user.setLoginstate(1);
				// 登录次数+1
				if (user.getLoginNum() != null) {
					user.setLoginNum(user.getLoginNum() + 1);
				} else {
					user.setLoginNum(1);
				}
				// 登录时间为当前时间
				user.setLoginDate(new Date());

				if (StringUtil.isNotEmpty(loginUser.getUuid())) {
					user.setUuid(loginUser.getUuid());
				}

				// 如果没有上传registrationID，就存USERID
				if (loginUser.getRegistrationID() != null) {
					user.setRegistrationID(loginUser.getRegistrationID() + user.getId());
				} else {
					user.setRegistrationID(user.getId().toString());
				}
				userService.updateLoginState(user);
				loginLogService.logIn(request);

			} else {
				result.setSuccessful(false);
				result.setMsg("用户名/密码错误");
			}
		} catch (UnknownAccountException e) {
			logger.error(e.getMessage(), e);
			result.setSuccessful(false);
			result.setMsg("用户名/密码错误");
		} catch (IncorrectCredentialsException e) {
			logger.error(e.getMessage(), e);
			result.setSuccessful(false);
			result.setMsg("用户名/密码错误");
		} catch (ExcessiveAttemptsException e) {
			logger.error(e.getMessage(), e);
			result.setSuccessful(false);
			result.setMsg("登录失败多次，账户锁定10分钟");
		} catch (AuthenticationException e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
		return result;
	}

}
