package com.yifu.cloud.plus.v1.permission.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.permission.mapper.SysMenuMapper;
import com.yifu.cloud.plus.v1.permission.mapper.SysRoleInfoMapper;
import com.yifu.cloud.plus.v1.permission.service.SysRoleInfoService;
import com.yifu.cloud.plus.v1.permission.service.SysRoleMenuResService;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysMenu;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysRoleInfo;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysRoleMenuRes;
import com.yifu.cloud.plus.v1.yifu.permission.vo.SysRoleInfoSaveVo;
import com.yifu.cloud.plus.v1.yifu.permission.vo.SysRoleInfoSearchVo;
import com.yifu.cloud.plus.v1.yifu.permission.vo.SysRoleMenuResSearchVo;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 新权限-角色表
 *
 * @author hgw
 * @date 2023-08-29 14:49:40
 */
@Log4j2
@Service
@AllArgsConstructor
public class SysRoleInfoServiceImpl extends ServiceImpl<SysRoleInfoMapper, SysRoleInfo> implements SysRoleInfoService {

	private final SysRoleMenuResService sysRoleMenuResService;
	private final SysMenuMapper sysMenuMapper;

	/**
	 * 新权限-角色表简单分页查询
	 *
	 * @param sysRoleInfo 新权限-角色表
	 * @return
	 */
	@Override
	public IPage<SysRoleInfo> getSysRoleInfoPage(Page<SysRoleInfo> page, SysRoleInfoSearchVo sysRoleInfo) {
		return baseMapper.getSysRoleInfoPage(page, sysRoleInfo);
	}

	@NotNull
	private Function<SysMenu, TreeNode<String>> getNodeFunction() {
		return menu -> {
			TreeNode<String> node = new TreeNode<>();
			node.setId(menu.getId());
			node.setName(menu.getMenuName());
			node.setParentId(menu.getMenuParentId());
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			extra.put("label", menu.getMenuName());
			node.setExtra(extra);
			return node;
		};
	}

	@Override
	public R<SysRoleInfoSaveVo> getInfoById(String fdId) {
		SysRoleInfoSaveVo vo = new SysRoleInfoSaveVo();
		SysRoleInfo role = this.getById(fdId);
		if (role != null && Common.isNotNull(role.getFdId())) {
			SysRoleMenuResSearchVo sysRoleMenuRes = new SysRoleMenuResSearchVo();
			sysRoleMenuRes.setRoleId(role.getFdId());
			List<SysRoleMenuRes> resList = sysRoleMenuResService.noPageDiy(sysRoleMenuRes);
			vo.setRole(role);
			vo.setResList(resList);
		}
		List<TreeNode<String>> collect = sysMenuMapper
				.selectList(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getDeleteStatus,CommonConstants.ONE_STRING)
						.eq(SysMenu::getPermissionStatus,CommonConstants.ZERO_STRING)
						.orderByAsc(SysMenu::getCreateTime)).stream()
				.map(getNodeFunction()).collect(Collectors.toList());
		List<Tree<String>> tree = TreeUtil.build(collect, CommonConstants.ZERO_STRING);
		vo.setTree(tree);
		return R.ok(vo);
	}

	/**
	 * @param vo
	 * @Description: 新增或编辑新权限-角色表
	 * @Author: hgw
	 * @Date: 2023/8/30 15:24
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> saveOrUpdateRoleInfo(SysRoleInfoSaveVo vo) {
		SysRoleInfo role = vo.getRole();
		List<SysRoleMenuRes> resList = vo.getResList();
		if (role != null && Common.isNotNull(role.getRoleName()) && resList != null && !resList.isEmpty()) {
			if (Common.isNotNull(role.getFdId())) {
				sysRoleMenuResService.deleteByRoleId(role.getFdId());
			}
			int num = baseMapper.checkExistenceRole(role.getRoleName(), role.getFdId());
			if (num > 0) {
				return R.failed("名称已存在");
			}
			this.saveOrUpdate(role);
			for (SysRoleMenuRes res : resList) {
				res.setRoleId(role.getFdId());
			}
			sysRoleMenuResService.saveBatch(resList);
			return R.ok("保存成功");
		}
		return R.failed("请检查信息");
	}

	@Override
	public List<SysRoleInfo> noPageDiy(SysRoleInfoSearchVo searchVo) {
		LambdaQueryWrapper<SysRoleInfo> wrapper = buildQueryWrapper(searchVo);
		List<String> idList = Common.getList(searchVo.getIds());
		if (Common.isNotNull(idList)) {
			wrapper.in(SysRoleInfo::getFdId, idList);
		}
		if (searchVo.getLimitStart() >= 0 && searchVo.getLimitEnd() > 0) {
			wrapper.last(" limit " + searchVo.getLimitStart() + "," + searchVo.getLimitEnd());
		}
		wrapper.orderByDesc(BaseEntity::getCreateTime);
		return baseMapper.selectList(wrapper);
	}

	@Override
	public String getAllRoleDataAuthByUserId(String userId) {
		List<String> authList = baseMapper.getAllRoleDataAuthByUserId(userId);
		return this.getAuths(authList);
	}

	/**
	 * @param roleIdList
	 * @Description: 给前端使用：根据角色id组合获取角色权限
	 * @Author: hgw
	 * @Date: 2023/9/8 9:25
	 * @return: java.lang.String
	 **/
	@Override
	public String getRoleDataAuthByRoleId(List<String> roleIdList) {
		List<String> authList = baseMapper.getRoleDataAuthByRoleId(roleIdList);
		return this.getAuths(authList);
	}

	private String getAuths(List<String> authList) {
		StringBuilder auths = new StringBuilder();
		if (authList != null && !authList.isEmpty()) {
			String[] authArr;
			Set<String> authSet = new HashSet<>();
			for (String auth : authList) {
				authArr = auth.split(",");
				Collections.addAll(authSet, authArr);
			}
			boolean flag = false;
			for (String subAuth : authSet) {
				if (flag) {
					auths.append(",").append(subAuth);
				} else {
					auths.append(subAuth);
					flag = true;
				}
			}
		}
		return auths.toString();
	}

	private LambdaQueryWrapper buildQueryWrapper(SysRoleInfoSearchVo entity) {
		LambdaQueryWrapper<SysRoleInfo> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(SysRoleInfo::getDeleteFlag, CommonConstants.ZERO_INT);
		if (Common.isNotNull(entity.getRoleName())) {
			wrapper.like(SysRoleInfo::getRoleName, entity.getRoleName());
		}
		if (Common.isNotNull(entity.getStatus())) {
			wrapper.eq(SysRoleInfo::getStatus, entity.getStatus());
		}
		if (Common.isNotNull(entity.getCreateTimeStart())) {
			wrapper.ge(SysRoleInfo::getCreateTime, entity.getCreateTimeStart());
		}
		if (Common.isNotNull(entity.getCreateTimeEnd())) {
			wrapper.le(SysRoleInfo::getCreateTime, entity.getCreateTimeEnd());
		}
		if (Common.isNotNull(entity.getCreateName())) {
			wrapper.eq(SysRoleInfo::getCreateName, entity.getCreateName());
		}
		return wrapper;
	}

}
