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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.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.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.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.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.ArrayList;
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 SysUserMchStoreRelaService mchStoreRelaService;
	@Autowired private MchInfoService mchInfoService;
	@Autowired private SysUserEntruleRelaService entruleRelaService;
	@Autowired private SmsManager smsManager;

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

		SysUserEntity queryObject = getObject(SysUserEntity.class);

		LambdaQueryWrapper<SysUserEntity> condition = SysUserEntity.gw();

		//  不包含普通操作员 ( APP不允许该操作 )
		if(queryObject.extv().getIntValue("isNotHasType2") == 1){
			condition.ne(SysUserEntity::getUserType, SysUser.UEST_TYPE_NORMAL);
		}

		condition.eq(SysUserEntity::getSysType, CS.SYS_ROLE_TYPE.MCH);
		condition.eq(SysUserEntity::getBelongInfoId, getCurrentUser().getSysUser().getBelongInfoId());

		if(StringUtils.isNotEmpty(queryObject.getRealname())){
			condition.like(SysUserEntity::getRealname, queryObject.getRealname());
		}

		if(queryObject.getSysUserId() != null){
			condition.eq(SysUserEntity::getSysUserId, queryObject.getSysUserId());
		}

		condition.like(StringUtils.isNotEmpty(queryObject.getTelphone()), SysUserEntity::getTelphone, queryObject.getTelphone());

		// 店长增加条件
		if (SysUser.UEST_TYPE_DIRECTOR == getCurrentUser().getSysUser().getUserType()) {
			// 用户为店长或店员类型
			condition.in(SysUserEntity::getUserType, SysUser.UEST_TYPE_DIRECTOR, SysUser.UEST_TYPE_CASHIER);

			// 当前绑定门店的所属用户
			List<String> storeIdList = getCurrentUser().getStoreIdList();
			List<SysUserMchStoreRela> relaList = mchStoreRelaService.list(
					SysUserMchStoreRela.gw().select(SysUserMchStoreRela::getSysUserId)
							.in(CollectionUtil.isNotEmpty(storeIdList), SysUserMchStoreRela::getStoreId, storeIdList)
			);
			ArrayList<Long> userIdList = new ArrayList<>();

			relaList.stream().forEach(item ->{
				userIdList.add(item.getSysUserId());
			});
			condition.in(CollectionUtil.isNotEmpty(userIdList), SysUserEntity::getSysUserId, userIdList);
		}

		condition.orderByDesc(SysUserEntity::getCreatedAt); // 时间 倒序
		IPage<SysUserEntity> pages = sysUserService.page(getIPage(), condition);

		// 数据脱敏
		pages.getRecords().stream().forEach(i-> {
			i.setTelphone(DesensitizedUtil.mobilePhone(i.getTelphone()));
			// 是否初始用户
			boolean ifInitUser = mchInfoService.count(MchInfo.gw().eq(MchInfo::getInitUserId, i.getSysUserId()).eq(MchInfo::getMchNo, i.getBelongInfoId())) >0;
			i.addExt("initUser", ifInitUser);
		});

		return ApiRes.page(pages);
	}


	/** 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 == null) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }
		if (!sysUserEntity.getBelongInfoId().equals(getCurrentUser().getSysUser().getBelongInfoId())) {
			throw new BizException(ApiCodeEnum.SYS_PERMISSION_ERROR);
		}
		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);
		}

		SysUserEntruleRela entruleRela = entruleRelaService.getById(recordId);
		if (entruleRela != null) {
			sysUserEntity.addExt("rulesList", JSONArray.parse(entruleRela.getRules()));
		}

		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);

		// 新增店长、店员 需为M1类型商户
		if (SysUser.UEST_TYPE_DIRECTOR == sysUserEntity.getUserType() || SysUser.UEST_TYPE_CASHIER == sysUserEntity.getUserType()) {
			MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
			if (mchInfo == null) {
				throw new BizException("商户不存在");
			}

			// 判断当前商户类型是否为M1商户
			if (!MchInfo.MCH_LEVEL_M1.equals(mchInfo.getMchLevel())) {
				throw new BizException("请先修改为M1商户");
			}
		}

		sysUserEntity.setBelongInfoId(getCurrentUser().getSysUser().getBelongInfoId());
//		sysUser.setUserType(com.jeequan.jeepay.core.entity.SysUser.UEST_TYPE_NORMAL);
//		sysUserService.addSysUser(sysUser, CS.SYS_ROLE_TYPE.MCH, loginPassword);
		sysUserService.addSysUser2(sysUserEntity, CS.SYS_ROLE_TYPE.MCH, loginPassword, getValString("storeIdList"), getValString("rulesList"));

		// 发送短信通知
		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.MCH);
		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.MCH).eq(SysUserEntity::getBelongInfoId, getCurrentMchNo()));
		if (dbRecord == null) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

//		boolean delAuthenticationFlag = sysUserService.updateUserOnTx(sysUser, recordId, getCurrentUser().getSysUserId());
		boolean delAuthenticationFlag = sysUserService.updateUserOnTx2(sysUserEntity, recordId,
				getCurrentUser().getSysUserId(), getValString("storeIdList"), getValString("rulesList"),
				getCurrentUser().getSysUser().getUserType());

		//查询到该角色的人员， 将redis更新
		authService.refAuthentication(Arrays.asList(recordId));

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

		return ApiRes.ok();
	}

	/** 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(mchInfoService.count(MchInfo.gw().eq(MchInfo::getInitUserId, recordId).eq(MchInfo::getMchNo, sysUserEntity.getBelongInfoId())) > 0 ){
			throw new BizException("系统不允许删除商户默认用户！");
		}

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

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

		}

		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("该操作员不存在！");
		}

		// 店员不支持该操作
		if (getCurrentUser().getSysUser().getUserType() == SysUser.UEST_TYPE_CASHIER) {
			throw new BizException(ApiCodeEnum.SYS_PERMISSION_ERROR);
		}

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





	/** 查询用户的 动态权限  */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
	@RequestMapping(value="/userEntRoles/{recordId}", method = RequestMethod.GET)
	public ApiRes userEntRoles(@PathVariable("recordId") Integer recordId) {
		SysUserEntruleRela entruleRela = entruleRelaService.getById(recordId);
		return ApiRes.ok(entruleRela);
	}

	/** 更新用户的动态权限  */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
	@RequestMapping(value="/userEntRoles/{recordId}", method = RequestMethod.PUT)
	public ApiRes updateUserEntRoles(@PathVariable("recordId") Long recordId) {

		// 更新单条记录
		String ruleName = getValStringRequired("ruleName");
		Byte state = getValByteRequired("state");

		entruleRelaService.updateUserEntRoles(recordId, state, ruleName);


		//查询到该角色的人员， 将redis更新
		authService.refAuthentication(Arrays.asList(recordId));

		return ApiRes.ok();
	}




}
