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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.components.mq.model.CleanAgentLoginAuthCacheMQ;
import com.jeequan.jeepay.components.mq.model.CleanMchLoginAuthCacheMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.smsconfig.SmsBizDiyContentModel;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
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.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/*
* 操作员列表
*
* @author terrfly
*
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("/api/sysUsers")
public class SysUserController extends CommonCtrl {

	@Autowired private SysUserService sysUserService;
	@Autowired private SysUserAuthService sysUserAuthService;
	@Autowired private AuthService authService;
	@Autowired private SysUserTeamService sysUserTeamService;
	@Autowired private IMQSender mqSender;
	@Autowired private SysUserMchStoreRelaService mchStoreRelaService;
	@Autowired private SysUserEntruleRelaService entruleRelaService;
	@Autowired private SmsManager smsManager;

	/** list */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_LIST' )")
	@GetMapping
	public ApiRes list() {

		SysUserEntity queryObject = getObject(SysUserEntity.class);

		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 -> {
			if (!StringUtils.equalsAny(item.getString("sysType"), CS.SYS_ROLE_TYPE.PLATFORM, CS.SYS_ROLE_TYPE.AGENT)) {
				item.put("inviteCode", "");
			}
			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 ifAgentInitUser = false;
			if (SysConfigService.IS_HAS_AGENT_ENT) {
				ifAgentInitUser = agentInfoService.count(AgentInfo.gw().eq(AgentInfo::getInitUserId, item.getLong("sysUserId")).eq(AgentInfo::getAgentNo, item.getString("belongInfoId"))) >0;
			}
			boolean ifMchInitUser = mchInfoService.count(MchInfo.gw().eq(MchInfo::getInitUserId, item.getLong("sysUserId")).eq(MchInfo::getMchNo, item.getString("belongInfoId"))) >0;
			item.put("initUser", ifAgentInitUser || ifMchInitUser);
		});

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


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

		SysUserEntity sysUserEntity = sysUserService.getById(recordId);

		if (sysUserEntity.getTeamId() != null) {
			SysUserTeam userTeam = sysUserTeamService.getById(sysUserEntity.getTeamId());

			sysUserEntity.addExt("teamName", userTeam.getTeamName());
		}

		// 如果为店长、店员查询所绑定门店信息
		if (SysUser.UEST_TYPE_DIRECTOR == sysUserEntity.getUserType() || SysUser.UEST_TYPE_CASHIER == sysUserEntity.getUserType()) {
			List<SysUserMchStoreRela> storeRelaList = mchStoreRelaService.list(SysUserMchStoreRela.gw().eq(SysUserMchStoreRela::getSysUserId, recordId));
			if (CollectionUtil.isNotEmpty(storeRelaList)) {
				ArrayList<String> storeIdList = new ArrayList<>();
				storeRelaList.forEach(item -> {
					storeIdList.add(item.getStoreId());
				});
				sysUserEntity.addExt("storeIdList", storeIdList);
			}
		}

		return ApiRes.ok(sysUserEntity);
	}

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

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

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


	/** 修改操作员 登录认证信息 */
//	@RequestMapping(value="/modifyPwd", method = RequestMethod.PUT)
//	@MethodLog(remark = "修改操作员密码")
	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.PLATFORM);
		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);

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

		// 返回最新用户信息
		SysUserEntity dbRecord = sysUserService.getById(recordId);

		// 删除用户redis缓存信息
		if(delAuthenticationFlag){

			// 删除商户系统用户redis
			if(CS.SYS_ROLE_TYPE.MCH.equals(dbRecord.getSysType())){

				// 推送mq删除redis用户缓存
				mqSender.send(CleanMchLoginAuthCacheMQ.build(Arrays.asList(recordId)));

			}else if(CS.SYS_ROLE_TYPE.AGENT.equals(dbRecord.getSysType())){

				// 推送mq删除redis用户缓存
				mqSender.send(CleanAgentLoginAuthCacheMQ.build(Arrays.asList(recordId)));

			} else if(CS.SYS_ROLE_TYPE.PLATFORM.equals(dbRecord.getSysType())){
				authService.delAuthentication(Arrays.asList(recordId));
			}
		}

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

		return ApiRes.ok(dbRecord);
	}

	/** 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("系统不允许删除当前登陆用户！");
		}
		// 删除用户
		sysUserService.removeUser(sysUserEntity, CS.SYS_ROLE_TYPE.PLATFORM);

		//如果用户被删除，需要更新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();
		}

		String sysType = authList.get(0).getSysType();

		List<String> loginUserNameList = new LinkedList<>();
		for (SysUserAuth sysUserAuth : authList) {

			// 平台用户直接清除redis
			if (CS.SYS_ROLE_TYPE.PLATFORM.equals(sysType)) {
				RedisUtil.del(CS.getCacheKeyLoginErr(CS.SYS_ROLE_TYPE.PLATFORM, sysUserAuth.getIdentifier()));
			}else {
				loginUserNameList.add(sysUserAuth.getIdentifier());
			}
		}

		// 服务商、商户系统  推送mq删除redis 登录限制缓存
		if (CS.SYS_ROLE_TYPE.AGENT.equals(sysType)) {
			mqSender.send(CleanAgentLoginAuthCacheMQ.build(loginUserNameList, CleanAgentLoginAuthCacheMQ.CLEAN_CACHE_TYPE_LOGIN_ERR));
		} else if (CS.SYS_ROLE_TYPE.MCH.equals(sysType)) {
			mqSender.send(CleanMchLoginAuthCacheMQ.build(loginUserNameList, CleanMchLoginAuthCacheMQ.CLEAN_CACHE_TYPE_LOGIN_ERR));
		}

		return ApiRes.ok();
	}

	/** 操作员绑定门店 */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
	@RequestMapping(value="/bindStore/{recordId}", method = RequestMethod.POST)
	@MethodLog(remark = "绑定门店")
	public ApiRes bindStore(@PathVariable("recordId") Long recordId) throws BizException{

		String storeIdList = getValString("storeIdList");

		//查询该操作员信息
		SysUserEntity sysUserEntity = sysUserService.getById(recordId);
		if (sysUserEntity == null) {
			throw new BizException("该操作员不存在！");
		}

		// 绑定门店
		mchStoreRelaService.bindStore(sysUserEntity, storeIdList);
		return ApiRes.ok();
	}
}
