package cn.common.service.impl;

import cn.common.common.constants.BaseConstant;
import cn.common.common.enums.ErrorCode;
import cn.common.common.exception.BusinessException;
import cn.common.common.redis.RedisRepository;
import cn.common.common.utils.collection.CollectionUtils;
import cn.common.common.utils.common.CheckParam;
import cn.common.interaction.helper.PageBuilder;
import cn.common.interaction.req.role.AuthRoleAddReq;
import cn.common.interaction.req.role.AuthRolePageReq;
import cn.common.interaction.req.role.AuthRoleUpdateReq;
import cn.common.interaction.resp.page.Pagination;
import cn.common.interaction.resp.role.AuthRolePageQueryResp;
import cn.common.repository.entity.AuthRole;
import cn.common.repository.entity.AuthRoleMenu;
import cn.common.repository.repository.AuthMenuRepository;
import cn.common.repository.repository.AuthPermissionRepository;
import cn.common.repository.repository.AuthRoleMenuRepository;
import cn.common.repository.repository.AuthRoleRepository;
import cn.common.repository.repository.PlatformUserConfigRepository;
import cn.common.repository.repository.AuthUserRepository;
import cn.common.repository.repository.AuthUserRoleRepository;
import cn.common.repository.repository.PlatformLoginLogRepository;
import cn.common.service.AuthCacheService;
import cn.common.service.AuthRoleService;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Singer create by singer email:singer-coder@qq.com
 * @projectName health-platform-api
 * @Description: 系统角色服务方法实现
 * @date 2019-08-23
 */
@Service(value = "authRoleService")
@Slf4j
public class AuthRoleServiceImpl implements AuthRoleService {

    @Resource
    private AuthUserRepository authUserRepository;

    @Resource
    private AuthPermissionRepository authPermissionRepository;

    @Resource
    private AuthRoleRepository authRoleRepository;

    @Resource
    private AuthUserRoleRepository authUserRoleRepository;

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private AuthCacheService authCacheService;

    @Resource
    private PlatformLoginLogRepository platformLoginLogRepository;

    @Resource
    private RedisRepository redisRepository;

    @Resource
    private PlatformUserConfigRepository platformUserConfigRepository;

    @Resource
    private AuthMenuRepository authMenuRepository;

    @Resource
    private AuthRoleMenuRepository authRoleMenuRepository;

    @Resource
    private MapperFacade mapperFacade;


    /**
      * 分页查询用户角色
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2019-08-23
      * @param authRolePageReq 分页查询用户角色参数
      * @return Pagination
      */
    @Override
    public Pagination<AuthRolePageQueryResp> queryAuthRoleByPage(AuthRolePageReq authRolePageReq){

        LambdaQueryWrapper<AuthRole> queryWrapper = new LambdaQueryWrapper<>();


        if(!CheckParam.isNull(authRolePageReq.getRoleName())){
            queryWrapper.eq(AuthRole::getRoleName,authRolePageReq.getRoleName());
        }
        if(!CheckParam.isNull(authRolePageReq.getOptionalStatus())){
            queryWrapper.eq(AuthRole::getOptionalStatus,authRolePageReq.getOptionalStatus());
        }
        if(!CheckParam.isNull((authRolePageReq.getBeginTime()))){
            queryWrapper.gt(AuthRole::getCreateTime,authRolePageReq.getBeginTime());
        }
        if(!CheckParam.isNull((authRolePageReq.getEndTime()))){
            queryWrapper.le(AuthRole::getCreateTime,authRolePageReq.getEndTime());
        }
        queryWrapper.orderByDesc(AuthRole::getCreateTime);
        List<AuthRole> authRoleList = new ArrayList<>();
        Page<Object> page = new Page();
        if(authRolePageReq.getNeedAll()){
            authRoleList.addAll(authRoleRepository.selectList(queryWrapper));
            page.setTotal(authRoleList.size());
            page.setPageSize(authRoleList.size());
            page.setPageNum(1);
            page.setPages(1);
        }else{
            //开始分页
            page = PageHelper.startPage(authRolePageReq.getCurrentPage(), authRolePageReq.getItemsPerPage());
            authRoleList.addAll(authRoleRepository.selectList(queryWrapper));
        }
        if(CheckParam.isNull(authRoleList) || authRoleList.isEmpty()) {
            return PageBuilder.buildPageResult(page,new ArrayList<>());
        }
        List<AuthRolePageQueryResp> authRoleRespList = new ArrayList<>();
        authRoleList.stream().forEach(u1 -> {
            AuthRolePageQueryResp resp = new AuthRolePageQueryResp();
            resp.setCreateTime(u1.getCreateTime());
            resp.setUpdateTime(u1.getUpdateTime());
            resp.setRemark(u1.getRemark());
            resp.setAuthRoleId(u1.getAuthRoleId());
            resp.setRoleName(u1.getRoleName());
            resp.setRoleCode(u1.getRoleCode());
            resp.setOptionalStatus(u1.getOptionalStatus());
            authRoleRespList.add(resp);
        });
        return PageBuilder.buildPageResult(page,authRoleRespList);
    }

    /**
      * 查询角色列表---不分页
      * @author: create by Singer email:singer-coder@qq.com
      * @date 2019/9/2
      * @return List
      */
    @Override
    public List<AuthRolePageQueryResp> queryAllRoles() {
        //查询出所有角色
        List<AuthRole> authRoleList = authRoleRepository.selectList(
                new LambdaQueryWrapper<>());
        List<AuthRolePageQueryResp> respList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(authRoleList)){
            return mapperFacade.mapAsList(authRoleList,AuthRolePageQueryResp.class);
        }
        return respList;
    }

    /**
      * 询角色对应的权限菜单
      * @author: create by Singer email:singer-coder@qq.com
      * @date 2019/9/4
      * @param authRoleId 角色ID
      * @return List
      */
    @Override
    public List<String> queryMenuIdList(String authRoleId) {
        log.info(">>>>>>>>>>>>>>>>查询对应角色的权限菜单,参数:{}<<<<<<<<<<<<<<<<<",authRoleId);
        //查询
        List<AuthRoleMenu> roleMenuList = authRoleMenuRepository.selectList(
                new LambdaQueryWrapper<AuthRoleMenu>().eq(AuthRoleMenu::getAuthRoleId, authRoleId));
        if(CollectionUtils.isEmpty(roleMenuList)){
            return Collections.EMPTY_LIST;
        }
        List<String> authMenuIdList = roleMenuList.stream().map(item -> item.getAuthMenuId()).collect(Collectors.toList());
        return authMenuIdList;
    }

    /**
     * 更新信息
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/3/30
     * @param updateReq 更新请求参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateItem(AuthRoleUpdateReq updateReq) {
        log.info(">>>>>>>>>>>>>修改角色信息,参数:{}<<<<<<<<<<<<<<<<",updateReq.toString());
        String roleCode = updateReq.getRoleCode();
        String optionalStatus = updateReq.getOptionalStatus();
        //查询
        AuthRole authRole = authRoleRepository.selectOne(new LambdaQueryWrapper<AuthRole>()
                .eq(AuthRole::getAuthRoleId, updateReq.getAuthRoleId()));
        if (!CheckParam.isNull(optionalStatus)){
            authRole.setOptionalStatus(optionalStatus);
        }
        //判断
        if (!CheckParam.isNull(updateReq.getRemark())&&!authRole.getRemark().equalsIgnoreCase(updateReq.getRemark())){
            authRole.setRemark(updateReq.getRemark());
        }
        if (!CheckParam.isNull(roleCode)){
            //角色代码不相同才执行更新
            if(!StrUtil.equalsAnyIgnoreCase(authRole.getRoleCode(),roleCode)){
                authRole.setRoleCode(roleCode);
            }
        }
        //更新
        authRoleRepository.updateById(authRole);
        //查询角色已有的权限
        List<AuthRoleMenu> menus = authRoleMenuRepository.selectList(
                new LambdaQueryWrapper<AuthRoleMenu>().eq(AuthRoleMenu::getAuthRoleId, updateReq.getAuthRoleId()));
        //取出所有的menuId
        List<String> oldMenuIds = menus.stream().map(menu -> menu.getAuthMenuId()).collect(Collectors.toList());
        //转换成set
        Set<String> oldSet = new HashSet<>(oldMenuIds);
        //现有的权限
        List<String> newMenuIdList = updateReq.getAuthMenuIdList();
        //转换成set
        Set<String> newSet = new HashSet<>(newMenuIdList);
        //需要删除的权限
        Set<String> flagSet = new HashSet<>();
        flagSet.addAll(oldSet);
        flagSet.removeAll(newSet);
        log.info(">>>>>>>>>>>>>>>更新新角色:{}->需要【删除】的权限:{} <<<<<<<<<",updateReq.getAuthRoleId(),flagSet.toString());
        if (!CheckParam.isNull(flagSet) && flagSet.size() > 0){
            flagSet.stream().forEach(menuId->{
                authRoleMenuRepository.deleteByRoleAndMenuId(updateReq.getAuthRoleId(),menuId);
            });
        }
        //需要新增的权限
        flagSet.clear();
        flagSet.addAll(newSet);
        flagSet.removeAll(oldSet);
        log.info(">>>>>>>>>>>>>>>更新新角色:{}->需要【添加】的权限:{}",updateReq.getAuthRoleId(),flagSet.toString());
        if (!CheckParam.isNull(flagSet) && flagSet.size() > 0){
            flagSet.stream().forEach(menuId->{
                AuthRoleMenu authRoleMenu = new AuthRoleMenu();
                authRoleMenu.setAuthRoleId(updateReq.getAuthRoleId());
                authRoleMenu.setAuthMenuId(menuId);
                authRoleMenuRepository.insert(authRoleMenu);
            });
        }
    }

    /**
      * 删除角色
      * @author: create by Singer email:singer-coder@qq.com
      * @date 2019/9/4
      * @param authRoleIdList
      */
    @Override
    public void batchDeleteItem(String authRoleIdList) {
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>删除用户角色,参数:{}<<<<<<<<<<<<<<<<<<<<<<<<",authRoleIdList);
        List<String> roleIdList = Arrays.asList(authRoleIdList.split(","));
        if (!CheckParam.isNull(roleIdList)){
            roleIdList.stream().forEach(authRoleId->{
                authRoleRepository.deleteByRoleId(authRoleId);
            });
            authRoleMenuRepository.deleteByAuthRoleIdList(roleIdList);
        }
    }

    /**
     * 判断角色名称是否存在
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/5/21
     * @param roleName 角色名称
     * @return Boolean
     */
    @Override
    public Boolean roleNameExisted(String roleName){
        Long roleCount = authRoleRepository.selectCount(new LambdaQueryWrapper<AuthRole>().eq(AuthRole::getRoleName, roleName));
        if(roleCount.compareTo(BigInteger.ZERO.longValue()) != 0){
            return true;
        }else{
            return false;
        }
    }

    /**
      * 判断角色代码是否存在
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2021/5/21
      * @param roleCode 角色代码
      * @return Boolean
      */
    @Override
    public Boolean roleCodeExisted(String roleCode){
        Long roleCount = authRoleRepository.selectCount(new LambdaQueryWrapper<AuthRole>().eq(AuthRole::getRoleCode, roleCode));
        if(roleCount.compareTo(BigInteger.ZERO.longValue()) != 0){
            return true;
        }else{
            return false;
        }
    }

    /**
      * 校验角色代码的唯一性
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2021/4/27
      * @param roleCode 角色代码
      */
    @Override
    public void verifyRoleCode(String roleCode){
        if(CheckParam.isNull(roleCode)){
            return;
        }
        Long roleCount = authRoleRepository.selectCount(new LambdaQueryWrapper<AuthRole>().eq(AuthRole::getRoleCode, roleCode));
        if(roleCount.compareTo(BigInteger.ZERO.longValue()) != 0){
            throw new BusinessException(ErrorCode.REPEAT_ROLE_CODE_ERROR.getCode(),
                    ErrorCode.REPEAT_ROLE_CODE_ERROR.getMessage());
        }
    }

    /**
     * 新增角色
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/3/30
     * @param addReq 新增角色请求参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addItem(AuthRoleAddReq addReq) {
        log.info(">>>>>>>>>>>>>>>>>新增角色请求参数: {} <<<<<<<<<<<<<<", JSON.toJSONString(addReq));
        String roleCode = addReq.getRoleCode();
        verifyRoleCode(roleCode);
        //创建角色
        AuthRole authRole = new AuthRole();
        authRole.setRemark(addReq.getRemark());
        authRole.setRoleName(addReq.getRoleName());
        authRole.setRoleCode(roleCode);
        authRole.setOptionalStatus(addReq.getOptionalStatus());
        authRoleRepository.insert(authRole);

        List<String> authMenuIdList = addReq.getAuthMenuIdList();
        //添加角色对应的菜单
        if (!CollectionUtils.isEmpty(authMenuIdList)){
            authMenuIdList.stream().forEach(authMenuId->{
                AuthRoleMenu authRoleMenu = new AuthRoleMenu();
                authRoleMenu.setAuthMenuId(authMenuId);
                authRoleMenu.setAuthRoleId(authRole.getAuthRoleId());
                authRoleMenuRepository.insert(authRoleMenu);
            });
        }
    }
}
