package com.yeejoin.precontrol.common.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.IdPasswordAuthModel;
import com.yeejoin.amos.feign.privilege.model.PermissionModel;
import com.yeejoin.amos.feign.privilege.model.VerifyCodeAuthModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.SmsRecordModel;
import com.yeejoin.precontrol.common.entity.*;
import com.yeejoin.precontrol.common.enums.*;
import com.yeejoin.precontrol.common.exception.CommonException;
import com.yeejoin.precontrol.common.mapper.AppMenuConfigMapper;
import com.yeejoin.precontrol.common.mapper.PersonMapper;
import com.yeejoin.precontrol.common.mapper.UserRegistrationMapper;
import com.yeejoin.precontrol.common.param.MobileLoginParam;
import com.yeejoin.precontrol.common.publish.MessageEventPublish;
import com.yeejoin.precontrol.common.service.*;
import com.yeejoin.precontrol.common.utils.DesUtil;
import com.yeejoin.precontrol.common.utils.MsgCodeUtil;
import com.yeejoin.precontrol.common.utils.RedisUtil;
import com.yeejoin.precontrol.common.utils.StringUtil;
import com.yeejoin.precontrol.common.vo.AppMenuConfigVo;
import com.yeejoin.precontrol.common.vo.UserRegistrationVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.Bean;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DELL
 */
@Service
@Slf4j
public class SafetyServiceImpl implements ISafetyService {

	private final int platformSuccessCode = 200;

	/**
	 * 文件服务器地址
	 */
	@Value("${fileserver.domain}")
	String fileServerUrl;

	@Value("${app.login.init.password}")
	private String password;
	/**
	 * 产品appkey
	 */
	@Value("${security.appKey}")
	private String appKey;
	/**
	 * 产品product
	 */
	@Value("${security.product}")
	private String product;
	/**
	 * 产品securityName
	 */
	@Value("${security.securityName}")
	private String securityName;

	/**
	 * redis有效时间
	 */
	@Value("${redis.key.expire.authCode}")
	private Long maxEffectTime;

	/**
	 * redis key前缀prefixAuthCode
	 */
	@Value("${redis.key.prefix.authCode}")
	private String prefixAuthCode;

	/**
	 * 是否放开微信管理员审核
	 */
	@Value("${need.weChat.admin.verify}")
	private Boolean needWeChatAdminVerify;

	/**
	 * 机构code
	 */
	@Value("${amos.agency.code}")
	private String agencyCode;

	/**
	 * 微信管理员校验码
	 */
	private final String fixedVerifyCode = "666666";

	/**
	 * 小程序端手机号验证码登录环境----方便在测试环境进行测试，不走平台的手机号验证码登录，直接走本地默认的 测试环境：dev 正式环境：product
	 */
	@Value("${login.environment}")
	private String loginEnvironment;

	@Autowired
	IPersonService iPersonService;
	/**
	 * http远程调用服务
	 */
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	IPersonAscriptionService iPersonAscriptionService;
	@Autowired
	IUserRegistrationService iUserRegistrationService;
	@Autowired
	SmallProServiceImpl smallProServiceImpl;
	@Autowired
	ISmsLogService iSmsLogService;
	@Autowired
	RedisUtil redisUtil;
	@Autowired
	MsgCodeUtil msgCodeUtil;
	@Autowired
	UserRegistrationMapper userRegistrationMapper;
	@Autowired
	IAppMenuConfigService iAppMenuConfigService;

	@Autowired
	AppMenuConfigMapper appMenuConfigMapper;

	@Autowired
	PersonMapper personMapper;

	@Autowired
	MessageEventPublish messageEventPublish;
	@Autowired
	private IAppMenuService appMenuService;

	@Value("${amos.secret.key}")
	String secretKey;

	/**
	 * 小程序手机号验证码登录,正式环境使用该方法 为了方便测试环境进行登录
	 */
	private Map<String, Object> loginFromAppDev(MobileLoginParam param) {
		// -1.前置初始化结构数据
		Map<String, Object> result = new LinkedHashMap<>();
		result.put("userState", "");
		result.put("userInfo", new HashMap<>());
		result.put("authInfo", new HashMap<>());
		Map<String, Object> userInfo = new LinkedHashMap<>();
		// 0.解析手机号
		String phoneNo = this.parsePhoneNo(param);
		// 1.判断是否需要进行短信验证码校验
		boolean isPassCheck = !param.getIsNeedVerify()
				|| ("dev".equals(loginEnvironment) && "666666".equals(param.getVerifyCode()));
		isPassCheck = this.smsVerifyCodeCheck(param.getIsNeedVerify(), param.getVerifyCode(), phoneNo);
		if (!isPassCheck) {
			throw new CommonException(600001, "短信验证不通过");
		}
		// 2.校验是否已经注册过
		List<UserRegistration> userList = this.getExistPerson(phoneNo);
		if (CollectionUtils.isEmpty(userList)) {
			// 没注册过，进行返回
			userInfo.put("phoneNo", phoneNo);
			result.put("userInfo", userInfo);
			result.put("userState", PersonCheckStatus.UN_REGISTER.getStatus());
			return result;
		}
		VerifyCodeAuthModel model = new VerifyCodeAuthModel();
		model.setLoginId(phoneNo);
		model.setVerifyCode(DesUtil.encode(phoneNo, phoneNo));
		FeignClientResult<Map<String, String>> mobileVerifyCodeResult = new FeignClientResult<>();
		RequestContext.setToken("token");
		RequestContext.setProduct(product);
		RequestContext.setAppKey(appKey);
		try {
			mobileVerifyCodeResult = Privilege.authClient.mobileVerifyCode(model);
		} catch (Exception e) {
			e.printStackTrace();
		}		
		if (mobileVerifyCodeResult.getStatus() != platformSuccessCode) {
			if (log.isErrorEnabled()) {
				log.error("调用平台手机号验证码登录失败:{}", mobileVerifyCodeResult.getDevMessage());
			}
			String message = mobileVerifyCodeResult.getMessage();
			if(StringUtils.isEmpty(message)) 
			{
				message="账号已被禁用,请联系管理员";
			}
			throw new CommonException(600001, message);
		}
		Map<String, Object> authInfo = new HashMap<>();
		// 设置authInfo信息
		authInfo.put("token", mobileVerifyCodeResult.getResult().get("token"));
		authInfo.put("personId", mobileVerifyCodeResult.getResult().get("userId"));
		authInfo.put("appKey", appKey);
		authInfo.put("product", product);
		result.put("authInfo", authInfo);
		// 设置userInfo信息
		UserRegistration user = userList.get(0);
		// 3.1用户状态信息
		result.put("userState", user.getVerifyStatus());
		// 3.2用户信息
		userInfo = this.buildUserInfo(user, phoneNo);
		result.put("userInfo", userInfo);
		// 非审核通过则不进行登录
		if (!user.getVerifyStatus().equals(PersonCheckStatus.DONE.getStatus())
				&& !user.getVerifyStatus().equals(PersonCheckStatus.INITED.getStatus())) {
			System.out.println("user--------->" + JSONObject.toJSONString(user));
			return result;
		}
		result.put("userState", user.getVerifyStatus());
		userInfo = this.buildUserInfo(user, phoneNo);
		result.put("userInfo", userInfo);
		return result;
	}

	/**
	 * 小程序手机号验证码登录,正式环境使用该方法
	 */
	private Map<String, Object> loginFromAppProduct(MobileLoginParam param) {
		// 初始化数据结构
		Map<String, Object> result = new HashMap<>();
		result.put("userState", "");
		result.put("userInfo", new HashMap<>());
		result.put("authInfo", new HashMap<>());
		Map<String, Object> userInfo = new HashMap<>();
		Map<String, Object> authInfo = new HashMap<>();
		// 通过手机号和验证码调用平台接口进行验证
		String phoneNo = this.parsePhoneNo(param);
		if (phoneNo == null) {
			throw new CommonException(600001, "获取手机号失败!");
		}
		// 设置userInfo信息
		List<UserRegistration> userList = this.getExistPerson(phoneNo);
		if (CollectionUtils.isEmpty(userList)) {
			// 没注册过，进行返回
			userInfo.put("phoneNo", phoneNo);
			result.put("userInfo", userInfo);
			result.put("userState", PersonCheckStatus.UN_REGISTER.getStatus());
			return result;
		}
		VerifyCodeAuthModel model = new VerifyCodeAuthModel();
		model.setLoginId(phoneNo);
		if (!param.getIsNeedVerify() || ("dev".equals(loginEnvironment) && "666666".equals(param.getVerifyCode()))) {
			model.setVerifyCode(DesUtil.encode(phoneNo, phoneNo));
		} else {
			model.setVerifyCode(param.getVerifyCode());
		}
		FeignClientResult<Map<String, String>> mobileVerifyCodeResult = new FeignClientResult<>();
		RequestContext.setToken("token");
		RequestContext.setProduct(product);
		RequestContext.setAppKey(appKey);
		mobileVerifyCodeResult = Privilege.authClient.mobileVerifyCode(model);
		if (mobileVerifyCodeResult.getStatus() != platformSuccessCode) {
			if (log.isErrorEnabled()) {
				log.error("调用平台手机号验证码登录失败:{}", mobileVerifyCodeResult.getDevMessage());
			}
			throw new CommonException(600001, mobileVerifyCodeResult.getMessage());
		}
		// 设置authInfo信息
		authInfo.put("token", mobileVerifyCodeResult.getResult().get("token"));
		authInfo.put("personId", mobileVerifyCodeResult.getResult().get("userId"));
		authInfo.put("appKey", appKey);
		authInfo.put("product", product);
		result.put("authInfo", authInfo);
		// 设置userInfo信息
		UserRegistration user = userList.get(0);
		// 3.1用户状态信息
		result.put("userState", user.getVerifyStatus());
		// 3.2用户信息
		userInfo = this.buildUserInfo(user, phoneNo);
		result.put("userInfo", userInfo);
		// 非审核通过则不进行登录
		if (!user.getVerifyStatus().equals(PersonCheckStatus.DONE.getStatus())
				&& !user.getVerifyStatus().equals(PersonCheckStatus.INITED.getStatus())) {
			System.out.println("user--------->" + JSONObject.toJSONString(user));
			return result;
		}
		result.put("userState", user.getVerifyStatus());
		userInfo = this.buildUserInfo(user, phoneNo);
		result.put("userInfo", userInfo);
		return result;
	}

	@Override
	public Map<String, Object> loginFromApp(MobileLoginParam param) {
		log.info("小程序端手机号验证码登录环境:{}", loginEnvironment);
		if ("dev".equals(loginEnvironment)) {
			return loginFromAppDev(param);
		} else if ("product".equals(loginEnvironment)) {
			return loginFromAppProduct(param);
		} else {
			throw new CommonException(600001, "小程序端手机号验证码登录环境参数有误!");
		}

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean registerFromApp(UserRegistrationVo vo) {
		if (log.isInfoEnabled()) {
			log.info("app发起注册请求参数：{}", JSON.toJSONString(vo));
		}
		boolean isExist = false;
		// 按照手机号查询是否进行注册过
		List<UserRegistration> userList = this.getExistPerson(vo.getPhoneNo());
		if (!CollectionUtils.isEmpty(userList)) {
			// 分支1：已注册
			isExist = true;
			// 1.更新rpm_user_registration表
			updateUserRegistration(vo);
			// 2.调用平台修改用户信息,只修改姓名
			if (log.isInfoEnabled()) {
				log.info("调用平台查询用户信息参数：{}", vo.getPhoneNo());
			}
			FeignClientResult<AgencyUserModel> result = Privilege.agencyUserClient
					.queryByUserId(userList.get(0).getUserId().toString());
			if (result.getStatus() == platformSuccessCode) {
				AgencyUserModel userModel = result.getResult();
				userModel.setRealName(vo.getRealName());
				if (log.isInfoEnabled()) {
					log.info("调用平台进行用户信息更新参数：{}", JSON.toJSONString(userModel));
				}
				FeignClientResult<AgencyUserModel> updateResult = Privilege.agencyUserClient.update(userModel,
						userList.get(0).getUserId().toString());
				if (updateResult.getStatus() != platformSuccessCode) {
					if (log.isErrorEnabled()) {
						log.error("调用平台更新用户信息失败:{}", updateResult.getDevMessage());
					}
					throw new CommonException(600001, updateResult.getMessage());
				}
			} else {
				if (log.isErrorEnabled()) {
					log.error("调用平台查询用户信息失败:{}", result.getDevMessage());
				}
				throw new CommonException(600001, "查询用户信息失败");
			}
		} else {
			// 分支2：未注册
			// 1.空插入rpm_user_registration表
			UserRegistration po = new UserRegistration();
			Bean.copyExistPropertis(vo, po);
			po.setVerifyStatus(PersonCheckStatus.WAIT_REGISTER.getStatus());
			// 2.调用平台创建用户信息
			AgencyUserModel userModel = buildAgencyUserModel(vo);
			FeignClientResult<AgencyUserModel> createResult = Privilege.agencyUserClient.create(userModel);
			if (createResult.getStatus() != platformSuccessCode) {
				if (log.isErrorEnabled()) {
					log.error("调用平台创建用户信息失败:{}", createResult.getDevMessage());
				}
				throw new CommonException(600001, createResult.getMessage());
			}
			userModel = createResult.getResult();
			if (StringUtil.isNotEmpty(userModel)) {
				po.setUserId(Long.parseLong(userModel.getUserId()));
				iUserRegistrationService.saveOrUpdate(po);
			}
		}
		// 消息通知--分包商主管进行人员审核
		// 查询该项目分包商主管
		List<Person> personList = personMapper.getFBSDirector(vo.getProjectId());
		List<Long> directorIdList = Lists.transform(personList, Person::getId);
		JSONArray array = new JSONArray();
		directorIdList.forEach(id -> {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put(MessageAttributeEnum.MSG_TYPE.getName(), MessageTypeEnum.AUDIT.getType());
			jsonObject.put(MessageAttributeEnum.MSG_SUB_TYPE.getName(), MessageSubTypeEnum.AUDIT_MSG.getType());
			jsonObject.put(MessageAttributeEnum.PERSON_ID.getName(), id);
			jsonObject.put(MessageAttributeEnum.CONTENT.getName(), MessageSubTypeEnum.AUDIT_MSG.getTip());
			array.add(jsonObject);
		});
		JSONObject data = new JSONObject();
		data.put("param", array);
		messageEventPublish.publish(data);
		return isExist;
	}

	@Override
	public UserRegistrationVo getRegisterHistory(String phoneNo) {
		UserRegistrationVo userRegistrationVo = new UserRegistrationVo();
		UserRegistration userRegistration = userRegistrationMapper
				.selectOne(new QueryWrapper<UserRegistration>().eq("phone_no", phoneNo));
		if (userRegistration != null) {
			BeanUtils.copyProperties(userRegistration, userRegistrationVo);
		}
		userRegistrationVo.setProfile(fileServerUrl+userRegistrationVo.getProfile());
		userRegistrationVo.setIdCardHead(fileServerUrl+userRegistrationVo.getIdCardHead());
		userRegistrationVo.setIdCardNational(fileServerUrl+userRegistration.getIdCardNational());
		return userRegistrationVo;
	}

	@Override
	public void getAuthCode(String phoneNo) {
		log.info("小程序端手机号验证码登录环境:{}", loginEnvironment);
		if ("dev".equals(loginEnvironment)) {
			getAuthCodeDev(phoneNo);
		} else if ("product".equals(loginEnvironment)) {
			getAuthCodeProduct(phoneNo);
		} else {
			throw new CommonException(600001, "小程序端手机号验证码登录环境参数有误!");
		}
	}

	public void getAuthCodeDev(String phoneNo) {
		// 1.校验手机号格式
		boolean isMobile = msgCodeUtil.isMobile(phoneNo);
		if (!isMobile) {
			throw new CommonException(600001, "非法的手机号");
		}
		// 2.生成二维码
		String authCode = msgCodeUtil.createRandomVcode(6);
		// 3.发送手机短信验证码
		String body = "";
		try {
			body = msgCodeUtil.verifyMsgSend(phoneNo, authCode);
		} catch (Exception e) {
			if (log.isErrorEnabled()) {
				log.error(e.getMessage(), e);
			}
			throw new CommonException(600001, "手机验证码发送失败");
		}
		// 3.记录发送短信流水，便于后期业务扩展
		this.saveSmgLog(phoneNo, authCode, body);
		// 4.设置短信到期时间,当前300秒
		redisUtil.set(prefixAuthCode + phoneNo, authCode, maxEffectTime);
	}

	public void getAuthCodeProduct(String phoneNo) {
		HashMap<String, String> sendMap = new HashMap<>();
		sendMap.put("mobile", phoneNo);
		sendMap.put("smsType", "MOBILE_LOGIN");
		FeignClientResult<SmsRecordModel> sendVerifyCodeResult = Systemctl.smsClient.sendVerifyCode(sendMap);
		if (sendVerifyCodeResult.getStatus() != platformSuccessCode) {
			if (log.isErrorEnabled()) {
				log.error("调用平台发送验证码失败:{}", sendVerifyCodeResult.getDevMessage());
			}
			throw new CommonException(600001, sendVerifyCodeResult.getMessage());
		}
	}

	@Override
	public List<AppMenuConfigVo> permissionMenuList(String userId) {
		List<AppMenuConfigVo> voList = new ArrayList<>();
		List<AppMenuConfig> pos;
		// 1.查询是否已经配置过菜单
		List<AppMenu> appMenus = appMenuService.list();
		pos = iAppMenuConfigService.list(new LambdaQueryWrapper<AppMenuConfig>().eq(AppMenuConfig::getUserId, userId)
				.orderByAsc(AppMenuConfig::getSort));
		if (!CollectionUtils.isEmpty(pos)) {
			voList = pos.stream().map(s -> {
				AppMenuConfigVo t = new AppMenuConfigVo();
				Bean.copyExistPropertis(s, t);
				t.setMenuIcon(getMenuIcon(appMenus, t.getMenuKey()));
				return t;
			}).collect(Collectors.toList());
			return voList;
		}
		// 2.没初始化，则进行初始化，插入数据
		String appMenu = "appMenu";
		/*
		 * List<PermissionModel> permissionModels = (List)
		 * Privilege.permissionClient.currentPermissionTree("APP", null, null,
		 * null).getResult(); Optional<PermissionModel> op =
		 * permissionModels.stream().filter(p ->
		 * p.getPath().equals(appMenu)).findFirst(); if (op.isPresent()) {
		 * List<PermissionModel> children = (List) op.get().getChildren(); // 2.1小程序功能显示
		 * pos = children.stream().map(p -> { AppMenu menu = findByMenuKey(p.getPath());
		 * AppMenuConfig appMenuConfig = new AppMenuConfig();
		 * appMenuConfig.setMenuKey(p.getPath());
		 * appMenuConfig.setMenuLabel(p.getPermissionName()); //
		 * appMenuConfig.setMenuIcon(menu.getMenuIcon());
		 * appMenuConfig.setSort(p.getSort()); appMenuConfig.setUserId(userId);
		 * appMenuConfig.setPage(menu.getPage()); // TODO
		 * 利用平台冗余字段'前端组件'，用来标识，是否是必须菜单，当前不为空即表示必须功能 if
		 * (StringUtil.isNotEmpty(p.getFrontComponent())) {
		 * appMenuConfig.setIsMust(true); appMenuConfig.setIsUsed(true); } else {
		 * appMenuConfig.setIsMust(false); appMenuConfig.setIsUsed(false); } return
		 * appMenuConfig; }).collect(Collectors.toList());
		 * iAppMenuConfigService.saveBatch(pos); }
		 */
		if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(appMenus)) {
			appMenus.stream().forEach(item -> {
				AppMenuConfig appMenuConfig = new AppMenuConfig();
				appMenuConfig.setMenuKey(item.getMenuKey());
				appMenuConfig.setMenuLabel(item.getMenuLabel());
				appMenuConfig.setMenuIcon(item.getMenuIcon());
				appMenuConfig.setSort(1);
				appMenuConfig.setUserId(userId);
				appMenuConfig.setPage(item.getPage());
				appMenuConfig.setIsMust(Boolean.FALSE);
				appMenuConfig.setIsUsed(Boolean.FALSE);
				if (item.getMenuKey().equals("riskWork")) {
					appMenuConfig.setIsMust(Boolean.TRUE);
					appMenuConfig.setIsUsed(Boolean.TRUE);
				}
				if (item.getMenuKey().equals("violateCheck")) {
					appMenuConfig.setIsMust(Boolean.TRUE);
					appMenuConfig.setIsUsed(Boolean.TRUE);
				}
				if (item.getMenuKey().equals("konwledgePush")) {
					appMenuConfig.setIsMust(Boolean.TRUE);
					appMenuConfig.setIsUsed(Boolean.TRUE);
				}
				if (item.getMenuKey().equals("myExam")) {
					appMenuConfig.setIsMust(Boolean.TRUE);
					appMenuConfig.setIsUsed(Boolean.TRUE);
				}
				pos.add(appMenuConfig);
			});
			iAppMenuConfigService.saveBatch(pos);
		}

		voList = pos.stream().map(s -> {
			AppMenuConfigVo t = new AppMenuConfigVo();
			Bean.copyExistPropertis(s, t);
			t.setMenuIcon(getMenuIcon(appMenus, t.getMenuKey()));
			return t;
		}).collect(Collectors.toList());
		return voList;
	}

	/**
	 * 获取菜单图标
	 *
	 * @param appMenus
	 * @param menuKey
	 * @return
	 */
	private String getMenuIcon(List<AppMenu> appMenus, String menuKey) {
		String icon = "";
		if (appMenus != null && appMenus.size() > 0 && StringUtil.isNotEmpty(menuKey)) {
			for (AppMenu appMenu : appMenus) {
				if (menuKey.equals(appMenu.getMenuKey())) {
//                    icon = fileServerUrl + appMenu.getMenuIcon();
					icon = appMenu.getMenuIcon();
				}
			}
		}
		return icon;
	}

	private AppMenu findByMenuKey(String menuKey) {
		List<AppMenu> appMenus = appMenuService.list();
		if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(appMenus)) {
			return appMenus.stream().filter(item -> item.getMenuKey().equals(menuKey)).findAny().orElse(null);
		}
		return new AppMenu();
	}

	@Override
	public List<AppMenuConfig> allPermissionMenuList(String userId) {
		// TODO 1.appMenu没放到请求url，原因平台bug->返回的children为null
		String appMenu = "appMenu";
		List<PermissionModel> permissionModels = (List) Privilege.permissionClient
				.currentPermissionTree("APP", null, null, null).getResult();
		Optional<PermissionModel> op = permissionModels.stream().filter(p -> p.getPath().equals(appMenu)).findFirst();
		List<AppMenu> appMenus = appMenuService.list();
		if (op.isPresent()) {
			List<PermissionModel> children = (List) op.get().getChildren();
			return children.stream().map(p -> {
				AppMenuConfig config = iAppMenuConfigService.getOne(new LambdaQueryWrapper<AppMenuConfig>()
						.eq(AppMenuConfig::getMenuKey, p.getPath()).eq(AppMenuConfig::getUserId, userId));
				AppMenuConfig appMenuConfig = new AppMenuConfig();
				if (config != null) {
					appMenuConfig.setMenuKey(p.getPath());
					appMenuConfig.setMenuLabel(p.getPermissionName());
					appMenuConfig.setMenuIcon(getMenuIcon(appMenus, config.getMenuKey()));
					appMenuConfig.setPage(config.getPage());
					appMenuConfig.setIsUsed(config.getIsUsed() != null ? config.getIsUsed() : false);
					appMenuConfig.setSort(p.getSort());
					appMenuConfig.setUserId(userId);
					appMenuConfig.setIsMust(config.getIsMust());
					appMenuConfig.setId(config.getId());
				}
				return appMenuConfig;
			}).collect(Collectors.toList());
		}
		return new ArrayList<>();
	}

	@Override
	public Boolean savePermission(String userId, List<AppMenuConfig> list) {
		// 1.删除
		if (CollectionUtils.isEmpty(list)) {
			return Boolean.FALSE;
		}
		list.stream().forEach(item -> {
			item.setMenuIcon("icon");
		});
		appMenuConfigMapper.delete(new LambdaQueryWrapper<AppMenuConfig>().eq(AppMenuConfig::getUserId, userId));
		// 2.插入
		return iAppMenuConfigService.saveBatch(list);
	}

	private void saveSmgLog(String phoneNo, String authCode, String body) {
		SmsLog smsLog = new SmsLog();
		smsLog.setAuthCode(authCode);
		smsLog.setReceiver(phoneNo);
		smsLog.setBody(body);
		smsLog.setStatus(1);
		iSmsLogService.save(smsLog);
	}

	private void updateUserRegistration(UserRegistrationVo vo) {
		QueryWrapper<UserRegistration> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(UserRegistration::getPhoneNo, vo.getPhoneNo());
		UserRegistration po = iUserRegistrationService.getOne(queryWrapper);
		Bean.copyExistPropertis(vo, po);
		po.setVerifyStatus(PersonCheckStatus.WAIT_REGISTER.getStatus());
		iUserRegistrationService.saveOrUpdate(po);
	}

	private AgencyUserModel buildAgencyUserModel(UserRegistrationVo vo) {
		AgencyUserModel userModel = new AgencyUserModel();
		userModel.setRealName(vo.getRealName());
		userModel.setPassword(DesUtil.encode(password, secretKey));
		userModel.setRePassword(DesUtil.encode(password, secretKey));
		userModel.setUserName(vo.getPhoneNo());
		userModel.setMobile(vo.getPhoneNo());
		userModel.setLockStatus("UNLOCK");
		return userModel;
	}

	private Map<String, Object> buildUserInfo(UserRegistration user, String phoneNo) {
		Map<String, Object> userInfo = new LinkedHashMap<>();
		userInfo.put("phoneNo", phoneNo);
		userInfo.put("companyId", user.getCompanyId());
		userInfo.put("projectId", user.getProjectId());
		userInfo.put("profile", user.getProfile());
		userInfo.put("idNumber", user.getIdNumber());
		userInfo.put("idType", user.getIdType());
		return userInfo;
	}

	private Map<String, Object> loginPlatform(String accountName, String password) {
		JSONObject jsonObject = null;
		IdPasswordAuthModel dPasswordAuthModel = new IdPasswordAuthModel();
		dPasswordAuthModel.setLoginId(accountName);
		dPasswordAuthModel.setPassword(password);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.set("Content-Type", "application/json");
		headers.set("product", product);
		HttpEntity httpEntity = new HttpEntity<>(dPasswordAuthModel, headers);
		FeignClientResult feignClientResult = restTemplate.postForObject(
				"http://" + securityName + "/privilege/v1/auth/idpassword", httpEntity, FeignClientResult.class);
		if (feignClientResult.getStatus() == platformSuccessCode) {
			Map map = (Map) feignClientResult.getResult();
			map.put("appKey", appKey);
			map.put("product", product);
			String jsonStr = JSON.toJSONString(map);
			jsonObject = JSONObject.parseObject(jsonStr);
		} else {
			throw new CommonException(600001, feignClientResult.getMessage());
		}
		if (jsonObject != null) {
			JSONObject result = new JSONObject();
			result.put("token", jsonObject.getString("token"));
			result.put("personId", jsonObject.getString("userId"));
			result.put("appKey", jsonObject.getString("appKey"));
			result.put("product", jsonObject.getString("product"));
			return result;
		}
		throw new CommonException(600001, "登录失败");
	}

	private List<UserRegistration> getExistPerson(String phoneNo) {
		return userRegistrationMapper.listAllUserContainUnVerify(phoneNo);
	}

	/**
	 * 短信验证
	 *
	 * @param isNeedVerify 是否需要验证
	 * @param verifyCode   验证码
	 * @param phoneNo      手机号
	 * @return 是否通过校验
	 */
	private boolean smsVerifyCodeCheck(Boolean isNeedVerify, String verifyCode, String phoneNo) {
		if (fixedVerifyCode.equals(verifyCode) && needWeChatAdminVerify) {
			return true;
		}
		if (!isNeedVerify) {
			return true;
		}
		return this.checkVerifyCode(phoneNo, verifyCode);
	}

	private boolean checkVerifyCode(String phoneNo, String verifyCode) {
		String key = this.buildKey(prefixAuthCode, phoneNo);
		Object existVerifyCode = redisUtil.get(key);
		if (ObjectUtils.isEmpty(existVerifyCode)) {
			throw new CommonException(700001, "验证码已过期，请重新发起获取短信验证码请求！");
		}
		if (!verifyCode.equals(existVerifyCode)) {
			throw new CommonException(700001, "验证不通过");
		}
		redisUtil.del(key);
		return true;
	}

	private String buildKey(String prefixAuthCode, String phoneNo) {
		return prefixAuthCode + phoneNo;
	}

	/**
	 * 手机号解析
	 *
	 * @param param MobileLoginParam.class
	 * @return String phoneNo
	 */
	private String parsePhoneNo(MobileLoginParam param) {
		if (param.getRegisterType() == PhoneRegisterTypeEum.WX.getCode()) {
			// 进行验证码解析
			String encryptedData = param.getEncryptedData();
			String iv = param.getIv();
			String code = param.getCode();
			return smallProServiceImpl.getPhoneNumber(smallProServiceImpl.getSessionKey(code), encryptedData, iv);
		} else {
			return param.getPhoneNo();
		}
	}
}
