package com.jeequan.jeepay.agent.ctrl.sysuser;

import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.agent.ctrl.CommonCtrl;
import com.jeequan.jeepay.agent.service.AuthService;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.smsconfig.SmsBizDiyContentModel;
import com.jeequan.jeepay.db.entity.AgentInfo;
import com.jeequan.jeepay.db.entity.SysUserAuth;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.db.entity.SysUserTeam;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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.RestController;

import java.util.Arrays;
import java.util.List;

/**
 * 用户管理类
 *
 * @author terrfly
 * @modify zhuxiao
 *
 * @date 2021-04-27 15:50
 */
@RestController
@RequestMapping("api/sysUsers")
public class SysUserController extends CommonCtrl {

	@Autowired SysUserService sysUserService;
	@Autowired SysUserAuthService sysUserAuthService;
	@Autowired SysConfigService sysConfigService;
	@Autowired private AuthService authService;
	@Autowired private SysUserTeamService sysUserTeamService;
	@Autowired private AgentInfoService agentInfoService;
	@Autowired private SmsManager smsManager;


	/** list */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_LIST' )")
	@RequestMapping(value="", method = RequestMethod.GET)
	public ApiRes list() {

		SysUserEntity queryObject = getObject(SysUserEntity.class);
		queryObject.setSysType(CS.SYS_ROLE_TYPE.AGENT);
		queryObject.setBelongInfoId(getCurrentAgentNo());

		// 是否app登录
		String loginType = getCurrentUser().getLoginType();
		boolean isApp = StringUtils.isNotBlank(loginType) && (loginType.equals(JWTPayload.LOGIN_PAGE_TYPE.APP) || loginType.equals(JWTPayload.LOGIN_PAGE_TYPE.LITE));

		// true表示是APP端
		if (isApp) {
			String queryNameOrPhone = getValString("queryNameOrPhone"); // 名字或手机号模糊查询
			LambdaQueryWrapper<SysUserEntity> queryWrapper = SysUserEntity.gw();
			queryWrapper.eq(SysUserEntity::getSysType, queryObject.getSysType());
			queryWrapper.eq(SysUserEntity::getBelongInfoId, queryObject.getBelongInfoId());
			queryWrapper.eq(null != queryObject.getUserType(), SysUserEntity::getUserType, queryObject.getUserType());

			if (StringUtils.isNotBlank(queryNameOrPhone)) {
				queryWrapper.and(wr -> {
					wr.like(SysUserEntity::getRealname, queryNameOrPhone)
							.or().like(SysUserEntity::getTelphone, queryNameOrPhone);
				});
			}

			IPage<SysUserEntity> iPage = sysUserService.page(getIPage(), queryWrapper);
			// 数据脱敏
			iPage.getRecords().stream().forEach(i -> i.setTelphone(DesensitizedUtil.mobilePhone(i.getTelphone())));
			return ApiRes.page(iPage);
		}


		long count = sysUserService.queryCount(queryObject);
		if (count <=0 ) {
			return ApiRes.page(new Page());
		}

		List<JSONObject> list = sysUserService.selectList(getIPage(), queryObject);

		// 邀请码二维码地址
		String mchRegisterUrl = String.format("%s/register", sysConfigService.getDBApplicationConfig().getMchSiteUrl());
		String agentRegisterUrl = String.format("%s/register", sysConfigService.getDBApplicationConfig().getAgentSiteUrl());
		list.forEach(item -> {
			item.put("inviteCodeUrl", String.format("%s?c=%s", mchRegisterUrl, item.getString("inviteCode")));
			item.put("agentInviteCodeUrl", String.format("%s?c=%s", agentRegisterUrl, item.getString("inviteCode")));

			// 数据脱敏
			item.put("telphone", DesensitizedUtil.mobilePhone(item.getString("telphone")));
			// 是否初始用户
			boolean ifInitUser = agentInfoService.count(AgentInfo.gw().eq(AgentInfo::getInitUserId, item.getLong("sysUserId")).eq(AgentInfo::getAgentNo, item.getString("belongInfoId"))) >0;
			item.put("initUser", ifInitUser);
		});

		return ApiRes.page(getIPage(), list, count);
	}


	/** detail */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_VIEW' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
	public ApiRes detail(@PathVariable("recordId") Integer recordId) {

		SysUserEntity sysUserEntity = sysUserService.getById(recordId);
		if (sysUserEntity == null) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }
		if (!sysUserEntity.getBelongInfoId().equals(getCurrentUser().getSysUser().getBelongInfoId())) {
			throw new BizException(ApiCodeEnum.SYS_PERMISSION_ERROR);
		}

		if (sysUserEntity.getTeamId() != null) {
			SysUserTeam sysUserTeam = sysUserTeamService.getById(sysUserEntity.getTeamId());
			if (sysUserTeam != null) {
				sysUserEntity.addExt("teamName", sysUserTeam.getTeamName());
			}
		}

		return ApiRes.ok(sysUserEntity);
	}

	/** add */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_ADD' )")
	@RequestMapping(value="", method = RequestMethod.POST)
	@MethodLog(remark = "添加管理员")
	public ApiRes add() {
		String loginPassword = getValString("loginPassword");
		Byte isNotify = getValByteRequired("isNotify");
		if (StringUtils.isBlank(loginPassword)) {
			loginPassword = null;
		}
		SysUserEntity sysUserEntity = getObject(SysUserEntity.class);
		sysUserEntity.setBelongInfoId(getCurrentUser().getSysUser().getBelongInfoId());

		sysUserService.addSysUser(sysUserEntity, CS.SYS_ROLE_TYPE.AGENT, loginPassword);

		// 发送短信通知
		if (isNotify == CS.YES) {
			smsManager.sendDiyContentSms(SmsBizDiyContentModel.genUserOpenAccount(sysUserEntity.getTelphone(), sysUserEntity.getLoginUsername(), loginPassword ));
		}

		return ApiRes.ok();
	}


	/** 修改操作员 登录认证信息 */
//	@RequestMapping(value="/modifyPwd", method = RequestMethod.PUT)
	public ApiRes authInfo() {

		Long opSysUserId = getValLongRequired("recordId");   //操作员ID

		//更改密码， 验证当前用户信息
		String currentUserPwd = getValStringRequired("originalPwd"); //当前用户登录密码
		//验证当前密码是否正确
		if(!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)){
			throw new BizException("原密码验证失败！");
		}

		String opUserPwd = getValStringRequired("confirmPwd");

		// 验证原密码与新密码是否相同
		if (opUserPwd.equals(currentUserPwd)) {
			throw new BizException("新密码与原密码相同！");
		}

		sysUserAuthService.resetAuthInfo(opSysUserId, null, null, true, opUserPwd, CS.SYS_ROLE_TYPE.AGENT);
		return ApiRes.ok();
	}


	/** update */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
	@MethodLog(remark = "修改操作员信息")
	public ApiRes update(@PathVariable("recordId") Long recordId) {

		SysUserEntity sysUserEntity = getObject(SysUserEntity.class);
		sysUserEntity.setSysUserId(recordId);

		// 避免越权操作
		SysUserEntity dbRecord = sysUserService.getOne(SysUserEntity.gw().eq(SysUserEntity::getSysUserId, recordId)
				.eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.AGENT).eq(SysUserEntity::getBelongInfoId, getCurrentAgentNo()));
		if (dbRecord == null) {
			throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
		}

		boolean delAuthenticationFlag = sysUserService.updateUserOnTx(sysUserEntity, recordId, getCurrentUser().getSysUserId());

		// 删除用户redis缓存信息
		if(delAuthenticationFlag){
			authService.delAuthentication(Arrays.asList(recordId));
		}

		// 返回最新用户信息
		SysUserEntity latestRecord = sysUserService.getById(recordId);
		// 邀请码二维码地址
		String mchRegisterUrl = String.format("%s/register", sysConfigService.getDBApplicationConfig().getMchSiteUrl());
		latestRecord.addExt("inviteCodeUrl", String.format("%s?c=%s", mchRegisterUrl, latestRecord.getInviteCode()));

		return ApiRes.ok(latestRecord);
	}

	/** delete */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_DELETE' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
	@MethodLog(remark = "删除操作员信息")
	public ApiRes delete(@PathVariable("recordId") Long recordId) {
		//查询该操作员信息
		SysUserEntity sysUserEntity = sysUserService.getById(recordId);
		if (sysUserEntity == null) {
			throw new BizException("该操作员不存在！");
		}

		//判断是否自己删除自己
		if(recordId.equals(getCurrentUser().getSysUser().getSysUserId())){
			throw new BizException("系统不允许删除当前登陆用户！");
		}

		//判断是否删除商户默认超管
		if(agentInfoService.count(AgentInfo.gw().eq(AgentInfo::getInitUserId, recordId).eq(AgentInfo::getAgentNo, sysUserEntity.getBelongInfoId())) > 0 ){
			throw new BizException("系统不允许删除服务商默认用户！");
		}

		// 删除用户
		sysUserService.removeUser(sysUserEntity, CS.SYS_ROLE_TYPE.AGENT);

		//如果用户被删除，需要更新redis数据
		authService.refAuthentication(Arrays.asList(recordId));

		return ApiRes.ok();
	}

	/** MFA验证 解绑 */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_MFA_DELETE' )")
	@RequestMapping(value="/mfaRelieve", method = RequestMethod.PUT)
	@MethodLog(remark = "MFA验证解除")
	public ApiRes mfaRelieve() throws BizException{
		Long recordId = getValLongRequired("recordId");
		// 当前登录账户是否为超管
		Long currentUserId = getCurrentUser().getSysUser().getSysUserId();
		// 解除操作员MFA验证
		sysUserService.relieveOperatorMFA(currentUserId, recordId);
		return ApiRes.ok();
	}

	/** 解除登录失败次数限制 */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_LOGIN_LIMIT_DELETE' )")
	@RequestMapping(value="/loginLimit/{recordId}", method = RequestMethod.DELETE)
	@MethodLog(remark = "解除登录限制")
	public ApiRes deleteLoginLimit(@PathVariable("recordId") Long recordId) throws BizException{

		List<SysUserAuth> authList = sysUserAuthService.list(SysUserAuth.gw().eq(SysUserAuth::getUserId, recordId));
		if (authList.isEmpty()) {
			return ApiRes.ok();
		}

		for (SysUserAuth sysUserAuth : authList) {

			RedisUtil.del(CS.getCacheKeyLoginErr(CS.SYS_ROLE_TYPE.AGENT, sysUserAuth.getIdentifier()));

		}

		return ApiRes.ok();
	}

	/** 提交审核 */
	@RequestMapping(value="/audit", method = RequestMethod.PUT)
	@MethodLog(remark = "提交审核")
	public ApiRes audit() throws BizException{

		// 提交的资料
		AgentInfo agentInfo = getObject(AgentInfo.class);
		// 查询数据库中的服务商信息
		AgentInfo dbAgentInfo = agentInfoService.getById(getCurrentAgentNo());
		if (dbAgentInfo == null) {
			throw new BizException("服务商信息不存在！");
		}

		if (dbAgentInfo.getState() == CS.YES) {
			throw new BizException("当前服务商已通过审核，不可修改信息！");
		}

		// 更新服务商资料
		AgentInfo updateInfo = new AgentInfo();
		updateInfo.setAgentNo(dbAgentInfo.getAgentNo());
		updateInfo.setState(AgentInfo.AUDIT_STATE_ING);

		updateInfo.setAgentName(agentInfo.getAgentName());				// 服务商名称
		updateInfo.setAgentShortName(agentInfo.getAgentShortName());	// 服务商简称
		updateInfo.setContactName(agentInfo.getContactName());			// 联系人姓名
		updateInfo.setContactEmail(agentInfo.getContactEmail());		// 联系人邮箱
		updateInfo.setLicenseImg(agentInfo.getLicenseImg());			// 营业执照
		updateInfo.setIdcard1Img(agentInfo.getIdcard1Img());			// 身份证人像面
		updateInfo.setIdcard2Img(agentInfo.getIdcard2Img());			// 身份证国徽面
		updateInfo.setIdcardInHandImg(agentInfo.getIdcardInHandImg());	// 手持身份证照
		updateInfo.setBankCardImg(agentInfo.getBankCardImg());			// 银行卡照片
		updateInfo.setPermitImg(agentInfo.getPermitImg());				// 许可证照片
		updateInfo.setAgentType(agentInfo.getAgentType());				// 服务商类型
		updateInfo.setSettAccountType(agentInfo.getSettAccountType());	// 账户类型
		updateInfo.setSettAccountNo(agentInfo.getSettAccountNo());		// 账户账号
		updateInfo.setSettAccountName(agentInfo.getSettAccountName());	// 账户姓名
		updateInfo.setSettAccountBank(agentInfo.getSettAccountBank());	// 银行名称
		updateInfo.setSettAccountSubBank(agentInfo.getSettAccountSubBank());	// 开户行支行名称

		agentInfoService.updateById(updateInfo);

		return ApiRes.ok();
	}

}
