package pwc.taxtech.atms.service.impl;

import org.apache.commons.lang3.BooleanUtils;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;
import pwc.taxtech.atms.common.CommonConstants;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.common.OperateLogType;
import pwc.taxtech.atms.common.OperationAction;
import pwc.taxtech.atms.common.OperationModule;
import pwc.taxtech.atms.common.RoleSourceEnum;
import pwc.taxtech.atms.common.UserStatus;
import pwc.taxtech.atms.common.message.LogMessage;
import pwc.taxtech.atms.common.message.UserMessage;
import pwc.taxtech.atms.constant.DimensionConstant;
import pwc.taxtech.atms.constant.UserConstant;
import pwc.taxtech.atms.dpo.DimensionValueOrgDto;
import pwc.taxtech.atms.dpo.OrganizationDto;
import pwc.taxtech.atms.dpo.RoleInfo;
import pwc.taxtech.atms.dpo.UserDto;
import pwc.taxtech.atms.dpo.UserOrgDto;
import pwc.taxtech.atms.dpo.UserOrgRoleDto;
import pwc.taxtech.atms.dpo.UserRoleQuery;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.UpdateLogParams;
import pwc.taxtech.atms.dto.organization.DimensionRoleDto;
import pwc.taxtech.atms.dto.organization.OrgCustomDto;
import pwc.taxtech.atms.dto.organization.OrgRoleDto;
import pwc.taxtech.atms.dto.organization.OrgRoleDtoList;
import pwc.taxtech.atms.dto.organization.SimpleRoleDto;
import pwc.taxtech.atms.dto.role.RoleDto;
import pwc.taxtech.atms.dto.user.DimensionUser;
import pwc.taxtech.atms.dto.user.NameDto;
import pwc.taxtech.atms.dto.user.OrganizationRoleInfo;
import pwc.taxtech.atms.dto.user.UpdateParam;
import pwc.taxtech.atms.dto.user.UserAndUserRoleSaveDto;
import pwc.taxtech.atms.dto.user.UserOrganizationDto;
import pwc.taxtech.atms.dto.user.UserRoleDimensionValueDto;
import pwc.taxtech.atms.dto.user.UserRoleDisplayInfo;
import pwc.taxtech.atms.dto.user.UserRoleQueryDto;
import pwc.taxtech.atms.entity.*;
import pwc.taxtech.atms.entity.UserRoleExample.Criteria;
import pwc.taxtech.atms.exception.ApplicationException;
import pwc.taxtech.atms.service.OrganizationService;
import pwc.taxtech.atms.service.PermissionService;
import pwc.taxtech.atms.service.UserRoleService;
import pwc.taxtech.atms.service.UserService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class UserRoleServiceImpl extends AbstractService implements UserRoleService {

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private OrganizationService organizationService;

    @Autowired
    private UserService userService;

    @Override
    public OrgRoleDtoList getUserRoleByUserID(String userID) {
        logger.debug("UserRoleServiceImpl getUserRoleByUserID [ userID: {} ]", userID);
        OrgRoleDtoList result = new OrgRoleDtoList();
        List<OrganizationRoleInfo> orgRoleInfoList = new ArrayList<>();
        if (!StringUtils.hasText(userID)) {
            return result;
        }

        // 原始角色
        List<RoleInfo> orignialUserRole = getOriginalRole(userID);

        // 维度附加角色
        List<UserOrgRoleDto> userDimensionValueRoleList = getUserDimensionValueRoleList();

        // 机构继承维度
        List<UserDimensionValueOrg> userDimensionValueOrgList = getUserDimensionValueOrgList();

        // 机构的附加角色
        List<UserOrgRoleDto> userOrganizationRoleList = getUserOrganizationRoleList();

        // 获取维度的基本数据
        List<UserRoleDimensionValueDto> basicQuery = getUserRoleDimensionValueBasic();

        // 维度的数据,可以是继承userRole的原始角色,也可以是附加的角色
        // 获取某个维度值下面的机构的用户角色
        List<UserRoleDimensionValueDto> dimensionOrgList = basicQuery.stream().filter(s -> userID.equals(s.getUserID()))
                .map(x -> CommonUtils.copyProperties(x, new UserRoleDimensionValueDto())).distinct()
                .collect(Collectors.toList());

        // 1. 维度上的角色
        for (UserRoleDimensionValueDto g : dimensionOrgList) {
            // 机构在维度上是否可以被继承,或者被访问
            UserDimensionValueOrg userDimensionValurOrg = userDimensionValueOrgList.stream()
                    .filter(uvg -> uvg.getUserDimensionValueID() != null && uvg.getOrganizationID() != null
                            && uvg.getUserDimensionValueID().equals(g.getID())
                            && uvg.getOrganizationID().equals(g.getOrganizationID()))
                    .findFirst().orElse(null);
            // 如果没有设置值,默认可以继承
            boolean isHeritable = userDimensionValurOrg == null
                    || BooleanUtils.isTrue(userDimensionValurOrg.getIsHeritable());
            if (!isHeritable) {
                continue;
            }
            // 不管允许不允许继承,都显示角色列表
            OrganizationRoleInfo orgRoleInfo = CommonUtils.copyProperties(g, new OrganizationRoleInfo());
            orgRoleInfo.setID(CommonUtils.getUUID());
            orgRoleInfo.setRoleList(new ArrayList<>());

            List<RoleInfo> roleInfoList = new ArrayList<>();

            // 1.1 继承原始角色
            if (BooleanUtils.isTrue(g.getHasOriginalRole()) && orignialUserRole != null
                    && !orignialUserRole.isEmpty()) {
                for (RoleInfo r : orignialUserRole) {
                    if (!roleInfoList.stream().anyMatch(s -> s.getID() != null && s.getID().equals(r.getID()))) {
                        roleInfoList.add(generateRoleInfo(r.getID(), r.getName(), RoleSourceEnum.Unknown.value()));
                    }
                }
            }

            // 1.2 维度的附加角色
            List<UserOrgRoleDto> userDimensionValueRole = userDimensionValueRoleList.stream()
                    .filter(udv -> udv.getID() != null && udv.getID().equals(g.getID())).collect(Collectors.toList());
            for (UserOrgRoleDto r : userDimensionValueRole) {
                if (!roleInfoList.stream().anyMatch(s -> s.getID() != null && s.getID().equals(r.getRoleID()))) {
                    roleInfoList.add(generateRoleInfo(r.getRoleID(), r.getRoleName(), RoleSourceEnum.Unknown.value()));
                }
            }
            orgRoleInfo.setRoleList(roleInfoList);
            orgRoleInfoList.add(orgRoleInfo);
        }
        // end.维度上的角色

        // 2 机构角色
        // 用户在机构可以添加原始角色,或者附加角色
        List<Map<String, Object>> userOrgList = myUserMapper.selectUserOrganizationMapByUserID(userID);

        for (Map<String, Object> userOrg : userOrgList) {
            boolean isAccessible = BooleanUtils.isTrue((Boolean) userOrg.get("isAccessible"));
            boolean hasOriginalRole = BooleanUtils.isTrue((Boolean) userOrg.get("hasOriginalRole"));

            List<RoleInfo> roleInfoList = new ArrayList<>();
            // 2.1 添加机构的附加原始角色
            if (hasOriginalRole && orignialUserRole != null && !orignialUserRole.isEmpty()) {
                for (RoleInfo r : orignialUserRole) {
                    if (!roleInfoList.stream().anyMatch(s -> s.getID() != null && s.getID().equals(r.getID()))) {
                        roleInfoList.add(generateRoleInfo(r.getID(), r.getName(), RoleSourceEnum.Unknown.value()));
                    }
                }
            }

            orgRoleInfoList.add(generateOrganizationRoleInfo(userOrg.get("organizationID").toString(),
                    userOrg.get("organizationName").toString(), DimensionConstant.OriginalRoleDimensionValueID,
                    DimensionConstant.OriginalRole, hasOriginalRole, isAccessible, roleInfoList, userID));
            List<RoleInfo> roleInfoList1 = new ArrayList<>();

            // 2.2 机构的附加(额外)角色,特殊权限
            List<UserOrgRoleDto> specialOrgRoleList = userOrganizationRoleList.stream()
                    .filter(urd -> urd.getID() != null && urd.getID().equals(userOrg.get("ID")))
                    .collect(Collectors.toList());

            if (!specialOrgRoleList.isEmpty()) {

                for (UserOrgRoleDto r : specialOrgRoleList) {
                    if (!roleInfoList1.stream().anyMatch(s -> s.getID() != null && s.getID().equals(r.getRoleID()))) {
                        roleInfoList1
                                .add(generateRoleInfo(r.getRoleID(), r.getRoleName(), RoleSourceEnum.Unknown.value()));
                    }
                }

                orgRoleInfoList.add(generateOrganizationRoleInfo(userOrg.get("organizationID").toString(),
                        userOrg.get("organizationName").toString(), DimensionConstant.ExtraOrgDimensionValueID,
                        DimensionConstant.ExtraOrgDimensionValueName, hasOriginalRole, isAccessible, roleInfoList1,
                        userID));
            }
        }

        // 机构上的角色
        List<OrgRoleDto> retList = new ArrayList<>();

        List<Map<String, String>> groupOrgRoleList = orgRoleInfoList.stream().map(this::rotateOrganizationRoleInfoToMap)
                .distinct().collect(Collectors.toList());
        for (Map<String, String> gr : groupOrgRoleList) {
            OrgRoleDto row = new OrgRoleDto();
            row.setOrgID(gr.get("organizationID"));
            row.setOrgName(gr.get("organizationName"));

            List<RoleInfo> roleList = new ArrayList<>();

            List<OrganizationRoleInfo> orgRoleList = orgRoleInfoList.stream().filter(
                    s -> s.getOrganizationID() != null && s.getOrganizationID().equals(gr.get("organizationID")))
                    .collect(Collectors.toList());
            if (orgRoleList.stream().anyMatch(x -> !BooleanUtils.isTrue(x.getIsAccessible()))) {
                row.setIsAccessible(false);
            } else {
                row.setIsAccessible(true);
            }

            for (OrganizationRoleInfo orgRole : orgRoleList) {
                for (RoleInfo role : orgRole.getRoleList()) {
                    if (!roleList.stream().anyMatch(x -> x.getID() != null && x.getID().equals(role.getID()))) {
                        roleList.add(role);
                    }
                }
            }
            row.setRoleList(roleList);
            retList.add(row);
        }

        result.setOrgRoleInfoList(orgRoleInfoList);
        result.setOrgDtoList(retList);

        return result;
    }

    private List<RoleInfo> getOriginalRole(String userID) {
        return userMapper.selectUserRoleInfoByID(userID);
    }

    private List<UserOrgRoleDto> getUserDimensionValueRoleList() {
        return userMapper.selectUserDimensionValueRole();
    }

    private List<UserDimensionValueOrg> getUserDimensionValueOrgList() {
        return userDimensionValueOrgMapper.selectByExample(new UserDimensionValueOrgExample());
    }

    private List<UserOrgRoleDto> getUserOrganizationRoleList() {
        return userMapper.selectUserOrganizationRole();
    }

    /**
     * 维度值下的用户角色列表,跟机构有绑定
     */
    private List<UserRoleDimensionValueDto> getUserRoleDimensionValueBasic() {
        List<DimensionValueOrgDto> basicQuery = getDimensionValueOrgDtoList();
        List<Map<String, Object>> userRoleDimensionValue = myUserMapper.selectUserDimensionValueMap();
        List<UserRoleDimensionValueDto> query = new ArrayList<>();
        for (DimensionValueOrgDto p : basicQuery) {
            List<Map<String, Object>> uList = userRoleDimensionValue.stream()
                    .filter(x -> p.getDimensionID() != null && p.getDimensionID().equals(x.get("dimensionID"))
                            && p.getDimensionValueID() != null
                            && p.getDimensionValueID().equals(x.get("dimensionValueID")))
                    .collect(Collectors.toList());
            if (uList.isEmpty()) {
                query.add(generateUserRoleDimensionValueDto(p, new HashMap<>()));
                continue;
            }
            for (Map<String, Object> u : uList) {
                query.add(generateUserRoleDimensionValueDto(p, u));
            }
        }
        return query;
    }

    private UserRoleDimensionValueDto generateUserRoleDimensionValueDto(DimensionValueOrgDto p, Map<String, Object> u) {
        UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
        userRoleDimensionValueDto.setOrganizationID(p.getOrganizationID());
        userRoleDimensionValueDto.setOrganizationName(p.getOrganizationName());
        userRoleDimensionValueDto.setID(Strings.sBlank(u.get("ID")));
        userRoleDimensionValueDto.setDimensionValueID(Strings.sBlank(u.get("dimensionValueID")));
        userRoleDimensionValueDto.setDimensionValueName(p.getDimensionValue());
        userRoleDimensionValueDto.setDimensionID(Strings.sBlank(u.get("dimensionID")));
        userRoleDimensionValueDto.setDimensionName(p.getDimensionName());
        userRoleDimensionValueDto.setUserID(Strings.sBlank(u.get("userID")));
        userRoleDimensionValueDto.setUserName(Strings.sBlank(u.get("userName")));
        userRoleDimensionValueDto.setIsAccessible(BooleanUtils.isTrue((Boolean) u.get("isAccessible")));
        userRoleDimensionValueDto.setHasOriginalRole(BooleanUtils.isTrue((Boolean) u.get("hasOriginalRole")));
        return userRoleDimensionValueDto;
    }

    private Map<String, String> rotateOrganizationRoleInfoToMap(OrganizationRoleInfo organizationRoleInfo) {
        Map<String, String> map = new HashMap<>();
        map.put("organizationID", organizationRoleInfo.getOrganizationID());
        map.put("organizationName", organizationRoleInfo.getOrganizationName());
        return map;
    }

    private List<DimensionValueOrgDto> getDimensionValueOrgDtoList() {
        return organizationService.getDimensionValueOrgDtoList();
    }

    @Override
    public UserAndUserRoleSaveDto getSingleUserByUserId(String userId) {
        UserAndUserRoleSaveDto userDto = new UserAndUserRoleSaveDto();
        User user = userMapper.selectByPrimaryKey(userId);
        if (user != null) {
            userDto = CommonUtils.copyProperties(user, new UserAndUserRoleSaveDto());
            // get role list by user
            List<Map<String, String>> query = myUserMapper.selectUserRoleListByUserID(userId).stream().distinct()
                    .collect(Collectors.toList());
            List<String> arrUserRole = new ArrayList<>();
            List<String> arrUserRoleName = new ArrayList<>();
            if (!query.isEmpty()) {
                for (Map<String, String> userRole : query) {
                    arrUserRole.add(userRole.get("roleID"));
                    arrUserRoleName.add(userRole.get("roleName"));
                }
            }
            userDto.setRoleIDs(arrUserRole);
            userDto.setRoleNames(arrUserRoleName);
            // get org name
            Organization org = organizationMapper.selectByPrimaryKey(user.getOrganizationID());
            if (org != null) {
                userDto.setOrgName(org.getName());
            }
        }
        return userDto;
    }

    @Override
    public List<UserRoleDisplayInfo> getAllUserRoleList(String serviceTypeID) {
        List<UserRoleQuery> query = userRoleMapper.selectUserRoleQueryByServiceTypeID(serviceTypeID);
        List<UserRoleDisplayInfo> userRoleDtoList = new ArrayList<>();
        List<UserRoleQueryDto> userList = query.stream().map(u -> CommonUtils.copyProperties(u, new UserRoleQueryDto()))
                .distinct().collect(Collectors.toList());
        for (UserRoleQueryDto item : userList) {
            UserRoleDisplayInfo dto = new UserRoleDisplayInfo();
            dto.setID(item.getUserID());
            dto.setUserID(item.getUserID());
            dto.setUserName(item.getUserName());
            dto.setOrganizationID(item.getOrgID());
            dto.setOrganizationName(item.getOrgName());
            dto.setEmail(item.getEmail());
            dto.setStatus(item.getStatus() ? 1 : 0);

            List<UserRoleQuery> roleList = query.stream().filter(s -> Objects.equals(s.getUserID(), item.getUserID()))
                    .distinct().collect(Collectors.toList());

            // 构造每个用户的角色列表
            List<RoleInfo> roleInfoList = new ArrayList<>();
            for (UserRoleQuery r : roleList) {
                if (!roleInfoList.stream().anyMatch(s -> Objects.equals(s.getID(), r.getRoleID()))) {
                    RoleInfo roleInfo = new RoleInfo();
                    roleInfo.setID(r.getRoleID());
                    roleInfo.setName(r.getRoleName());
                    roleInfo.setRoleSource(RoleSourceEnum.OriginalLevel.value());

                    roleInfoList.add(roleInfo);
                }
            }
            dto.setRoleInfoList(roleInfoList);
            userRoleDtoList.add(dto);
        }
        return userRoleDtoList;
    }

    @Override
    public List<UserRole> findAllUserRoles() {
        UserRoleExample userRoleExample = new UserRoleExample();
        return userRoleMapper.selectByExample(userRoleExample);
    }

    @Override
    public UserRoleDisplayInfo getUserRoleListByUserID(String userID) {
        List<UserRoleDisplayInfo> allUserList = getAllUserRoleList("2");
        return allUserList.stream().filter(s -> s.getUserID() != null && s.getUserID().equals(userID)).findFirst()
                .orElse(new UserRoleDisplayInfo());
    }

    /**
     * 某个机构下的所有权限 任何一个不可访问,就不可访问,任何的维度,和附加
     */
    @Override
    public UserOrganizationDto getUserRoleByOrgID(String userID, String orgID) {
        logger.debug("UserRoleServiceImpl getUserRoleByOrgID [ userID: {}, orgID: {} ]", userID, orgID);
        UserOrganizationDto userOrganizationDto = new UserOrganizationDto();
        userOrganizationDto.setDimensionUserList(new ArrayList<>());
        DimensionUser dimensionUser = null;
        User user = userMapper.selectByPrimaryKey(userID);
        if (user == null) {
            return userOrganizationDto;
        }
        Organization org = organizationMapper.selectByPrimaryKey(orgID);
        if (org == null) {
            return userOrganizationDto;
        }
        // 整个机构是否可访问
        List<Boolean> allIsAccessibleList = new ArrayList<>();
        userOrganizationDto.setUserName(user.getUserName());
        userOrganizationDto.setOrganizationName(org.getName());

        // 原始角色
        List<RoleInfo> orignialUserRole = getOriginalRole(userID);

        // 维度附加角色
        List<UserOrgRoleDto> userDimensionValueRoleList = getUserDimensionValueRoleList();

        // 机构继承维度
        List<UserDimensionValueOrg> userDimensionValueOrgList = getUserDimensionValueOrgList();

        // 机构的附加角色
        List<UserOrgRoleDto> userOrganizationRoleList = getUserOrganizationRoleList();

        // 获取维度的基本数据
        List<UserRoleDimensionValueDto> basicQuery = getUserRoleDimensionValueBasic();

        // 用户机构表
        List<UserOrganization> userOrganizationList = getUserOrganizationList();
        // 维度的数据,可以是继承userRole的原始角色,也可以是附加的角色
        // 获取某个维度值下面的机构的用户角色
        List<UserRoleDimensionValueDto> dimensionOrgList = basicQuery.stream()
                .filter(s -> Objects.equals(orgID, s.getOrganizationID()) && Objects.equals(userID, s.getUserID()))
                .map(s -> CommonUtils.copyProperties(s, new UserRoleDimensionValueDto())).distinct()
                .collect(Collectors.toList());
        // 维度上的角色
        for (UserRoleDimensionValueDto d : dimensionOrgList) {
            // 机构在维度上是否可以被继承,或者被访问
            UserDimensionValueOrg userDimensionValurOrg = userDimensionValueOrgList.stream()
                    .filter(uvg -> Objects.equals(d.getID(), uvg.getUserDimensionValueID())
                            && Objects.equals(d.getOrganizationID(), uvg.getOrganizationID()))
                    .findFirst().orElse(null);
            // 如果没有设置值,默认可以继承
            boolean isHeritable = userDimensionValurOrg == null
                    || BooleanUtils.isTrue(userDimensionValurOrg.getIsHeritable());
            // 任何一个维度上不可访问,且机构继承这个维度,那么这个机构就不可访问
            if (isHeritable && !BooleanUtils.isTrue(d.getIsAccessible())) {
                allIsAccessibleList.add(false); // 不可访问
            }
            // 不管允许不允许继承,都显示角色列表
            dimensionUser = CommonUtils.copyProperties(d, new DimensionUser());
            dimensionUser.setID(CommonUtils.getUUID());
            dimensionUser.setIsHeritable(isHeritable);
            dimensionUser.setRoleList(new ArrayList<>());

            List<NameDto> roleInfoList = new ArrayList<>();

            // 1.1 继承原始角色
            if (BooleanUtils.isTrue(d.getHasOriginalRole()) && orignialUserRole != null
                    && !orignialUserRole.isEmpty()) {
                for (RoleInfo r : orignialUserRole) {
                    if (!roleInfoList.stream().anyMatch(s -> Objects.equals(s.getID(), r.getID()))) {
                        roleInfoList.add(generateNameDto(r.getID(), r.getName(), RoleSourceEnum.Unknown.value()));
                    }
                }
            }

            // 1.2 维度的附加角色
            List<UserOrgRoleDto> userDimensionValueRole = userDimensionValueRoleList.stream()
                    .filter(udv -> Objects.equals(udv.getID(), d.getID())).collect(Collectors.toList());
            for (UserOrgRoleDto r : userDimensionValueRole) {
                if (!roleInfoList.stream().anyMatch(s -> Objects.equals(s.getID(), r.getID()))) {
                    roleInfoList.add(generateNameDto(r.getRoleID(), r.getRoleName(), RoleSourceEnum.Unknown.value()));
                }
            }

            dimensionUser.setRoleList(roleInfoList);
            userOrganizationDto.getDimensionUserList().add(dimensionUser);
        }
        // 用户在机构可以添加原始角色,或者附加角色
        UserOrganization userOrg = userOrganizationList.stream()
                .filter(ur -> Objects.equals(orgID, ur.getOrganizationID()) && Objects.equals(userID, ur.getUserID()))
                .findFirst().orElse(null);
        if (userOrg != null) {
            boolean isAccessible = BooleanUtils.isTrue(userOrg.getIsAccessible());
            boolean hasOriginalRole = BooleanUtils.isTrue(userOrg.getHasOriginalRole());
            if (!isAccessible) {
                allIsAccessibleList.add(false); // 用户机构不可访问,这是最高优先级
            }
            // 是否可以继承原始角色
            userOrganizationDto.setHasOriginalRole(hasOriginalRole);

            // 2.1 添加机构的附加原始角色
            if (hasOriginalRole) {
                List<NameDto> roleInfoList = new ArrayList<>();

                if (orignialUserRole != null && !orignialUserRole.isEmpty()) {
                    for (RoleInfo r : orignialUserRole) {
                        if (!roleInfoList.stream().anyMatch(s -> Objects.equals(s.getID(), r.getID()))) {
                            roleInfoList.add(generateNameDto(r.getID(), r.getName(), RoleSourceEnum.Unknown.value()));
                        }
                    }
                }
                userOrganizationDto.getDimensionUserList()
                        .add(generateDimensionUser(DimensionConstant.OriginalRoleDimensionValueID,
                                DimensionConstant.OriginalRole, hasOriginalRole, isAccessible, roleInfoList, userID,
                                user.getUserName()));
            }
            List<NameDto> roleInfoList1 = new ArrayList<>();

            // 2.2 机构的附加(额外)角色,特殊权限
            List<UserOrgRoleDto> specialOrgRoleList = userOrganizationRoleList.stream()
                    .filter(urd -> Objects.equals(urd.getID(), userOrg.getID())).collect(Collectors.toList());
            if (!specialOrgRoleList.isEmpty()) {
                for (UserOrgRoleDto r : specialOrgRoleList) {
                    if (!roleInfoList1.stream().anyMatch(s -> Objects.equals(s.getID(), r.getID()))) {
                        roleInfoList1
                                .add(generateNameDto(r.getRoleID(), r.getRoleName(), RoleSourceEnum.Unknown.value()));
                    }
                }
                userOrganizationDto.getDimensionUserList()
                        .add(generateDimensionUser(DimensionConstant.ExtraOrgDimensionValueID,
                                DimensionConstant.ExtraOrgDimensionValueName, hasOriginalRole, isAccessible,
                                roleInfoList1, userID, user.getUserName()));
            }
        }
        if (!allIsAccessibleList.isEmpty()) {
            // 这儿的可访问是需要计算的
            userOrganizationDto.setIsAccessible(false);
        } else {
            userOrganizationDto.setIsAccessible(true);
        }
        List<String> roleIdList = new ArrayList<>();
        // 加上权限
        // 维度上的,继承的可访问的
        List<DimensionUser> dimensionRoleList = userOrganizationDto.getDimensionUserList().stream()
                .filter(s -> !DimensionConstant.ExtraOrgDimensionID.equals(s.getDimensionID())
                        && BooleanUtils.isTrue(s.getIsHeritable()) && BooleanUtils.isTrue(s.getIsAccessible()))
                .collect(Collectors.toList());
        for (DimensionUser item : dimensionRoleList) {
            List<String> temp = item.getRoleList().stream().map(NameDto::getID).collect(Collectors.toList());
            roleIdList.addAll(temp);
        }
        // 机构上的,继承的原始的,和附加的
        List<DimensionUser> orgRoleList = userOrganizationDto.getDimensionUserList().stream()
                .filter(s -> DimensionConstant.ExtraOrgDimensionID.equals(s.getDimensionID())
                        && BooleanUtils.isTrue(s.getIsAccessible()))
                .collect(Collectors.toList());
        for (DimensionUser item : orgRoleList) {
            List<String> temp = item.getRoleList().stream().map(NameDto::getID).collect(Collectors.toList());
            roleIdList.addAll(temp);
        }
        roleIdList = roleIdList.stream().distinct().collect(Collectors.toList());
        userOrganizationDto.setPermissionTreeList(permissionService.getIvhTreePermissionsByRoleIDList(roleIdList, "2"));
        return userOrganizationDto;
    }

    private List<UserOrganization> getUserOrganizationList() {
        return myUserMapper.selectUserOrganizationByUserID();
    }

    private OrganizationRoleInfo generateOrganizationRoleInfo(String organizationID, String organizationName,
            String dimensionValueID, String dimensionValueName, Boolean hasOriginalRole, Boolean isAccessible,
            List<RoleInfo> roleInfoList, String userID) {
        OrganizationRoleInfo orgRoleInfo = new OrganizationRoleInfo();
        orgRoleInfo.setID(CommonUtils.getUUID());
        orgRoleInfo.setOrganizationID(organizationID);
        orgRoleInfo.setOrganizationName(organizationName);
        orgRoleInfo.setDimensionID(DimensionConstant.ExtraOrgDimensionID);
        orgRoleInfo.setDimensionName(DimensionConstant.ExtraOrgDimensionName);
        orgRoleInfo.setDimensionValueID(dimensionValueID);
        orgRoleInfo.setDimensionValueName(dimensionValueName);
        orgRoleInfo.setHasOriginalRole(hasOriginalRole);
        orgRoleInfo.setIsAccessible(isAccessible);
        orgRoleInfo.setRoleList(roleInfoList);
        orgRoleInfo.setUserID(userID);
        return orgRoleInfo;
    }

    private DimensionUser generateDimensionUser(String dimensionValueID, String dimensionValueName,
            Boolean hasOriginalRole, Boolean isAccessible, List<NameDto> roleInfoList, String userID, String userName) {
        DimensionUser dimensionUser = new DimensionUser();
        dimensionUser.setID(CommonUtils.getUUID());
        dimensionUser.setDimensionID(DimensionConstant.ExtraOrgDimensionID);
        dimensionUser.setDimensionName(DimensionConstant.ExtraOrgDimensionName);// 附加机构的特殊角色
        dimensionUser.setDimensionValueID(dimensionValueID);// 附加原始角色维度值ID
        dimensionUser.setDimensionValueName(dimensionValueName);// 附加原始角色
        dimensionUser.setHasOriginalRole(hasOriginalRole);
        dimensionUser.setIsAccessible(isAccessible);
        dimensionUser.setRoleList(roleInfoList);
        dimensionUser.setUserID(userID);
        dimensionUser.setUserName(userName);
        return dimensionUser;
    }

    private NameDto generateNameDto(String id, String name, Integer roleSource) {
        NameDto roleInfo = new NameDto();
        roleInfo.setID(id);
        roleInfo.setName(name);
        roleInfo.setRoleSource(roleSource);
        return roleInfo;
    }

    private RoleInfo generateRoleInfo(String id, String name, Integer roleSource) {
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setID(id);
        roleInfo.setName(name);
        roleInfo.setRoleSource(roleSource);
        return roleInfo;
    }

    @Override
    public List<DimensionRoleDto> getOrgBuAreaIndustryUser(String userID) {
        List<DimensionUser> list = getUserDimensionValueRole(userID);
        return list.stream().map(this::rotateDimensionUserToDimensionRoleDto).collect(Collectors.toList());
    }

    private DimensionRoleDto rotateDimensionUserToDimensionRoleDto(DimensionUser dimensionUser) {
        DimensionRoleDto dimensionRoleDto = CommonUtils.copyProperties(dimensionUser, new DimensionRoleDto());
        List<SimpleRoleDto> simpleRoleDtos = new ArrayList<>();
        if (dimensionUser.getRoleList() != null) {
            simpleRoleDtos = dimensionUser.getRoleList().stream().map(d -> {
                SimpleRoleDto simpleRoleDto = new SimpleRoleDto();
                simpleRoleDto.setRoleID(d.getID());
                simpleRoleDto.setRoleName(d.getName());
                simpleRoleDto.setRoleSource(d.getRoleSource());
                return simpleRoleDto;
            }).collect(Collectors.toList());
        }
        dimensionRoleDto.setRoleList(simpleRoleDtos);
        return dimensionRoleDto;
    }

    private List<DimensionUser> getUserDimensionValueRole(String userID) {
        List<DimensionUser> retlist = new ArrayList<>();
        // 维度的附加角色
        List<UserOrgRoleDto> userDimensionValueRoleList = getUserDimensionValueRoleList();
        // 原始角色
        List<RoleInfo> orignialUserRole = getOriginalRole(userID);
        List<UserRoleDimensionValueDto> diemensionValueList = getUserRoleDimensionValue().stream()
                .filter(x -> userID != null && userID.equals(x.getUserID()))
                .map(this::reserveNecessaryUserRoleDimensionValueDtoFieldForDistinct).distinct()
                .collect(Collectors.toList());
        for (UserRoleDimensionValueDto dv : diemensionValueList) {
            DimensionUser userRole = new DimensionUser();
            List<NameDto> roleInfoList = new ArrayList<>();
            if (dv != null) {
                userRole = CommonUtils.copyProperties(dv, userRole);
                // 2.1 添加原始角色
                if (BooleanUtils.isTrue(dv.getHasOriginalRole()) && orignialUserRole != null
                        && !orignialUserRole.isEmpty()) {
                    for (RoleInfo r : orignialUserRole) {
                        if (!roleInfoList.stream().anyMatch(s -> s.getID() != null && s.getID().equals(r.getID()))) {
                            roleInfoList
                                    .add(generateNameDto(r.getID(), r.getName(), RoleSourceEnum.OriginalLevel.value()));
                        }
                    }
                }
                // 2.2 附加(额外)角色,特殊权限
                List<UserOrgRoleDto> specialOrgRoleList = userDimensionValueRoleList.stream()
                        .filter(urd -> urd.getID() != null && urd.getID().equals(dv.getID()))
                        .collect(Collectors.toList());
                if (!specialOrgRoleList.isEmpty()) {
                    for (UserOrgRoleDto r : specialOrgRoleList) {
                        roleInfoList.add(
                                generateNameDto(r.getRoleID(), r.getRoleName(), RoleSourceEnum.DimensionLevel.value()));
                    }
                }
            }
            userRole.setRoleList(roleInfoList);
            retlist.add(userRole);
        }
        return retlist;
    }

    private UserRoleDimensionValueDto reserveNecessaryUserRoleDimensionValueDtoFieldForDistinct(
            UserRoleDimensionValueDto x) {
        UserRoleDimensionValueDto y = new UserRoleDimensionValueDto();
        y.setID(x.getID());
        y.setIsAccessible(x.getIsAccessible());
        y.setHasOriginalRole(x.getHasOriginalRole());
        y.setDimensionID(x.getDimensionID());
        y.setDimensionName(x.getDimensionName());
        y.setDimensionValueID(x.getDimensionValueID());
        y.setDimensionValueName(x.getDimensionValueName());
        return y;
    }

    private UserRoleDimensionValueDto reserveNecessaryUserOrgRelatedFieldForDistinct(UserRoleDimensionValueDto x) {
        UserRoleDimensionValueDto y = new UserRoleDimensionValueDto();
        y.setID(x.getID());
        y.setIsAccessible(x.getIsAccessible());
        y.setHasOriginalRole(x.getHasOriginalRole());
        y.setDimensionID(x.getDimensionID());
        y.setDimensionValueID(x.getDimensionValueID());
        y.setUserID(x.getUserID());
        y.setUserName(x.getUserName());
        y.setOrganizationID(x.getOrganizationID());
        y.setOrganizationName(x.getOrganizationName());
        return y;
    }

    /**
     * 维度、用户和机构无关的join连接
     */
    private List<UserRoleDimensionValueDto> getUserRoleDimensionValue() {
        // 在Dimension表中,机构层级的DimensionID=c61a5bd6-a996-4952-9869-d053966537e8
        // 在Dimension表中,事业部的DimensionID=c61a5bd6-a996-4952-9869-d053995237e5
        List<DimensionValueOrgDto> basicQuery = myUserMapper
                .selectUserRoleDimensionValueByDimensionID(DimensionConstant.BusinessUnitID);
        List<UserDimensionValue> userRoleDimensionValue = userDimensionValueMapper
                .selectByExample(new UserDimensionValueExample());
        List<UserRoleDimensionValueDto> query = new ArrayList<>();
        for (DimensionValueOrgDto p : basicQuery) {
            List<UserDimensionValue> uList = userRoleDimensionValue.stream()
                    .filter(u -> p.getDimensionID() != null && p.getDimensionID().equals(u.getDimensionID())
                            && p.getDimensionValueID() != null
                            && p.getDimensionValueID().equals(u.getDimensionValueID()))
                    .collect(Collectors.toList());
            if (uList.isEmpty()) {
                query.add(generateUserRoleDimensionValueDto(p, new UserDimensionValue()));
                continue;
            }
            for (UserDimensionValue u : uList) {
                query.add(generateUserRoleDimensionValueDto(p, u));
            }
        }
        return query;
    }

    private UserRoleDimensionValueDto generateUserRoleDimensionValueDto(DimensionValueOrgDto p, UserDimensionValue u) {
        UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
        userRoleDimensionValueDto.setOrganizationID(p.getOrganizationID());
        userRoleDimensionValueDto.setOrganizationName(p.getOrganizationName());
        userRoleDimensionValueDto.setID(Strings.sBlank(u.getID()));
        userRoleDimensionValueDto.setDimensionValueID(Strings.sBlank(u.getDimensionValueID()));
        userRoleDimensionValueDto.setDimensionValueName(p.getDimensionValue());
        userRoleDimensionValueDto.setDimensionID(Strings.sBlank(u.getDimensionID()));
        userRoleDimensionValueDto.setDimensionName(p.getDimensionName());
        userRoleDimensionValueDto.setUserID(Strings.sBlank(u.getUserID()));
        userRoleDimensionValueDto.setIsAccessible(BooleanUtils.isTrue(u.getIsAccessible()));
        userRoleDimensionValueDto.setHasOriginalRole(BooleanUtils.isTrue(u.getHasOriginalRole()));
        return userRoleDimensionValueDto;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto enableOrDisableUser(UpdateParam updateParam) {
        logger.debug("UserRoleServiceImpl enableOrDisableUser");
        OperationResultDto operationResultDto = new OperationResultDto();
        try {
            if (updateParam == null || !StringUtils.hasText(updateParam.getUserID())) {
                throw new ApplicationException("primary key can't be null");
            }
            User query = userMapper.selectByPrimaryKey(updateParam.getUserID());
            if (query == null) {
                throw new ApplicationException("can't find user with userID: " + updateParam.getUserID());
            }
            User userOriginal = CommonUtils.copyProperties(query, new User());
            if (UserConstant.DISABLE_TYPE.equals(updateParam.getUpdateType())) {
                query.setStatus(UserStatus.InActive.value());
                UserRoleExample userRoleExample = new UserRoleExample();
                Criteria criteria = userRoleExample.createCriteria();
                criteria.andUserIDEqualTo(updateParam.getUserID());
                criteria.andProjectIDIsNotNull();
                List<UserRole> userRoleList = userRoleMapper.selectByExample(userRoleExample);
                if (!userRoleList.isEmpty()) {
                    operationResultDto.setResult(false);
                    operationResultDto.setResultMsg(UserMessage.ExistsProjectCannotDisable);
                    return operationResultDto;
                }
            } else {
                query.setStatus(UserStatus.Active.value());
            }
            userMapper.updateByPrimaryKey(query);
            updateDataAddLog(userOriginal, query, OperationModule.User.value(), LogMessage.UpdateUser,
                    userOriginal.getUserName(), "operation content", OperateLogType.OperationLogUser.value());
            operationResultDto.setResult(true);
            return operationResultDto;
        } catch (Exception e) {
            logger.error("Error happens: {}", e);
            logger.error("Start to rollback...");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            operationResultDto.setResult(false);
            operationResultDto.setResultMsg(UserMessage.DisableUserFailed);
            return operationResultDto;
        }
    }

    private void updateDataAddLog(Object originalObj, Object updateObj, Integer operationModule, String comment,
            String operationObject, String operationContent, Integer logType) {
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperationObject(operationObject);
        updateLogParams.setOriginalState(originalObj);
        updateLogParams.setOperationContent(operationContent);
        updateLogParams.setUpdateState(updateObj);
        updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor());
        updateLogParams.setOperationModule(operationModule);
        updateLogParams.setOperationAction(OperationAction.Update.value());
        updateLogParams.setOperateLogType(logType);
        updateLogParams.setComment(comment);
        operationLogService.updateDataAddLog(updateLogParams);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto deleteUserRoleOrg(List<UserRoleDimensionValueDto> list) {
        logger.debug("UserRoleServiceImpl deleteUserRoleOrg");
        if (list == null) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }
        OperationResultDto operationResultDto = new OperationResultDto<>();
        UserRoleDimensionValueDto first = list.isEmpty() ? null : list.get(0);
        if (first != null) {
            // 1. 删除机构上
            UserOrganizationExample userOrganizationExample = new UserOrganizationExample();
            pwc.taxtech.atms.entity.UserOrganizationExample.Criteria criteria = userOrganizationExample
                    .createCriteria();
            criteria.andUserIDEqualTo(first.getUserID());
            criteria.andOrganizationIDEqualTo(first.getOrganizationID());
            List<UserOrganization> userOrganizationValueList = userOrganizationMapper
                    .selectByExample(userOrganizationExample);
            for (UserOrganization userOrganization : userOrganizationValueList) {
                logger.debug("Delete user organizaion with id [ {} ]", userOrganization.getID());
                userOrganizationMapper.deleteByPrimaryKey(userOrganization.getID());
            }
            addOrDeleteDataAddLog(getOrgDtoByID(first.getOrganizationID()).getName(),
                    getUserDtoByID(first.getUserID()).getUserName(), OperationModule.UserOrganization.value(),
                    OperationAction.Delete.value(), "");
        }
        List<UserRoleDimensionValueDto> dimensionList = list.stream()
                .filter(s -> !DimensionConstant.ExtraOrgDimensionID.equals(s.getDimensionID()))
                .collect(Collectors.toList());
        for (UserRoleDimensionValueDto item : dimensionList) {
            // 2.删除维度上的
            updateUserDimensionNonAccess(item);
        }
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    @Override
    public UserDto getUserDtoByID(String userID) {
        User query = userMapper.selectByPrimaryKey(userID);
        return query == null ? new UserDto() : CommonUtils.copyProperties(query, new UserDto());
    }

    @Override
    public OrganizationDto getOrgDtoByID(String orgID) {
        Organization query = organizationMapper.selectByPrimaryKey(orgID);
        return query == null ? new OrganizationDto() : CommonUtils.copyProperties(query, new OrganizationDto());
    }

    private void addOrDeleteDataAddLog(String orgName, String operateUserName, Integer module, Integer action,
            String comment) {
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setComment(comment);
        updateLogParams.setOperateLogType(OperateLogType.OperationLogUser.value());
        updateLogParams.setOperationModule(module);
        updateLogParams.setOperationContent(orgName);
        updateLogParams.setOperationAction(action);
        updateLogParams.setOperationObject(operateUserName);
        updateLogParams.setUpdateState("");
        updateLogParams.setOriginalState("");
        operationLogService.addOrDeleteDataAddLog(updateLogParams);
    }

    /**
     * 机构在维度上的,设置可继承或者不可继承
     */
    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto updateUserDimensionNonAccess(UserRoleDimensionValueDto r) {
        OperationResultDto operationResultDto = new OperationResultDto<>();
        if (r == null) {
            operationResultDto.setResult(true);
            return operationResultDto;
        }
        OrgCustomDto dimension = organizationService.getDimensionValueName(r.getDimensionID(), r.getDimensionValueID());
        String dimensionName = dimension.getDimensionName();
        String dimensionValueName = dimension.getDimensionValueName();
        String operateUserName = getUserDtoByID(r.getUserID()).getUserName();
        String orgName = getOrgDtoByID(r.getOrganizationID()).getName();

        List<UserDimensionValueOrg> userDimensionValueOrgList = getUserDimensionValueOrgList();
        // 机构在维度上的,设置可继承或者不可继承
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        pwc.taxtech.atms.entity.UserDimensionValueExample.Criteria criteria = userDimensionValueExample
                .createCriteria();
        criteria.andUserIDEqualTo(r.getUserID());
        criteria.andDimensionIDEqualTo(r.getDimensionID());
        criteria.andDimensionValueIDEqualTo(r.getDimensionValueID());
        List<UserDimensionValue> userDimensionList = userDimensionValueMapper
                .selectByExample(userDimensionValueExample);
        for (UserDimensionValue udv : userDimensionList) {
            List<UserDimensionValueOrg> oldList = userDimensionValueOrgList.stream()
                    .filter(p -> udv.getID() != null && udv.getID().equals(p.getUserDimensionValueID())
                            && p.getOrganizationID() != null && p.getOrganizationID().equals(r.getOrganizationID()))
                    .collect(Collectors.toList());
            if (oldList != null && !oldList.isEmpty()) {
                for (UserDimensionValueOrg m : oldList) {
                    UserDimensionValueOrg newObject = CommonUtils.copyProperties(m, new UserDimensionValueOrg());
                    newObject.setIsHeritable(BooleanUtils.isTrue(r.getIsHeritable()));
                    userDimensionValueOrgMapper.updateByPrimaryKey(newObject);

                    // 添加日志
                    updateDataAddLog(m, newObject, OperationModule.UserDimensionValueOrg.value(), "", operateUserName,
                            dimensionName + CommonConstants.DashSignSeparator + dimensionValueName
                                    + CommonConstants.DashSignSeparator + orgName + CommonConstants.DashSignSeparator
                                    + operateUserName,
                            OperateLogType.OperationLogUser.value());
                }
            } else {
                // 没有就添加一条
                UserDimensionValueOrg userRole = new UserDimensionValueOrg();
                userRole.setID(CommonUtils.getUUID());
                userRole.setUserDimensionValueID(udv.getID());
                userRole.setOrganizationID(r.getOrganizationID());
                userRole.setIsHeritable(BooleanUtils.isTrue(r.getIsHeritable()));
                userDimensionValueOrgMapper.insert(userRole);

                // 添加日志
                addOrDeleteDataAddLog(
                        dimensionName + CommonConstants.DashSignSeparator + dimensionValueName
                                + CommonConstants.DashSignSeparator + orgName + CommonConstants.DashSignSeparator
                                + operateUserName,
                        operateUserName, OperationModule.UserDimensionValueOrg.value(), OperationAction.New.value(),
                        "");
            }
        }
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    @Override
    public List<UserRoleDisplayInfo> getUserRoleByDimensionValueID(String parentDimensionID, String dimensionValueID) {
        List<UserRoleDisplayInfo> retlist = new ArrayList<>();
        // 用户在维度可以添加原始角色,或者附加角色
        List<UserDimensionValue> diemensionValueList = findUserDimensionValueByDimensionRelatedID(parentDimensionID,
                dimensionValueID, null);
        List<UserOrgRoleDto> userDimensionValueRoleList = getUserDimensionValueRoleList();

        for (UserDimensionValue item : diemensionValueList) {
            // 原始角色
            List<RoleInfo> orignialUserRole = getOriginalRole(item.getUserID());
            User userObject = findUserByStatusAndID(UserStatus.Active.value(), item.getUserID());
            String userName = userObject == null ? "" : userObject.getUserName();
            UserRoleDisplayInfo ur = new UserRoleDisplayInfo();
            ur.setUserID(item.getUserID());
            ur.setUserName(userName);
            // 查看是否有不可访问的,不可访问优先
            ur.setIsAccessible(BooleanUtils.isTrue(item.getIsAccessible()));
            ur.setHasOriginalRole(BooleanUtils.isTrue(item.getHasOriginalRole()));

            // 构造每个用户的角色列表
            List<RoleInfo> roleInfoList = new ArrayList<>();
            // 维度的角色,附加的角色
            List<UserOrgRoleDto> extraRole = userDimensionValueRoleList.stream()
                    .filter(p -> p.getID() != null && p.getID().equals(item.getID())).collect(Collectors.toList());
            if (extraRole != null && !extraRole.isEmpty()) {
                for (UserOrgRoleDto r : extraRole) {
                    roleInfoList.add(
                            generateRoleInfo(r.getRoleID(), r.getRoleName(), RoleSourceEnum.DimensionLevel.value()));
                }
            }
            // 添加原始角色
            if (orignialUserRole != null && !orignialUserRole.isEmpty()) {
                for (RoleInfo r : orignialUserRole) {
                    roleInfoList.add(generateRoleInfo(r.getID(), r.getName(), RoleSourceEnum.OriginalLevel.value()));
                }
            }
            ur.setRoleInfoList(roleInfoList);
            retlist.add(ur);
        }
        return retlist;
    }

    @Override
    public List<UserRoleDisplayInfo> getSpecialUserRoleByDimensionValueID(String parentDimensionID,
            String dimensionValueID) {
        List<UserRoleDisplayInfo> retlist = new ArrayList<>();
        // 获取特殊角色基本数据
        List<UserRoleDimensionValueDto> basicQuery = getOrgSpecialUserRoleList();

        // 获取某个维度值下面的用户角色
        List<UserRoleDimensionValueDto> dimensionValueList = basicQuery.stream()
                .filter(s -> parentDimensionID != null && parentDimensionID.equals(s.getDimensionID())
                        && dimensionValueID != null && dimensionValueID.equals(s.getDimensionValueID()))
                .collect(Collectors.toList());
        List<UserRoleDimensionValueDto> userRoleList = dimensionValueList.stream()
                .map(this::reserveNecessaryUserOrgRelatedFieldForDistinct).distinct().collect(Collectors.toList());
        List<UserOrgRoleDto> userOrganizationRoleList = getUserOrganizationRoleList();
        // 每个用户可能多个角色
        for (UserRoleDimensionValueDto item : userRoleList) {
            UserRoleDisplayInfo ur = CommonUtils.copyProperties(item, new UserRoleDisplayInfo());
            // 构造每个用户的角色列表
            List<RoleInfo> roleInfoList = new ArrayList<>();
            // 维度的角色,要么是原始角色,要么附加的角色
            List<UserOrgRoleDto> extraRole = userOrganizationRoleList.stream()
                    .filter(p -> p.getID() != null && p.getID().equals(item.getID())).collect(Collectors.toList());
            if (extraRole != null && !extraRole.isEmpty()) {
                for (UserOrgRoleDto r : extraRole) {
                    if (roleInfoList.stream().noneMatch(s -> s.getID() != null && s.getID().equals(r.getRoleID()))) {
                        roleInfoList
                                .add(generateRoleInfo(r.getRoleID(), r.getRoleName(), RoleSourceEnum.Unknown.value()));
                    }
                }
            }

            // 添加原始角色
            if (BooleanUtils.isTrue(ur.getHasOriginalRole())) {
                List<RoleInfo> orignialUserRole = getOriginalRole(item.getUserID());
                if (orignialUserRole != null && !orignialUserRole.isEmpty()) {
                    for (RoleInfo r : orignialUserRole) {
                        if (roleInfoList.stream().noneMatch(s -> s.getID() != null && s.getID().equals(r.getID()))) {
                            roleInfoList.add(generateRoleInfo(r.getID(), r.getName(), RoleSourceEnum.Unknown.value()));
                        }
                    }
                }
            }
            ur.setRoleInfoList(roleInfoList);
            retlist.add(ur);
        }
        return retlist;
    }

    private List<UserRoleDimensionValueDto> getOrgSpecialUserRoleList() {
        List<DimensionValueOrgDto> basicQuery = getDimensionValueOrgDtoList();
        List<Map<String, Object>> userRoleOrganization = myUserMapper.selectUserOrganizationMap();
        List<UserRoleDimensionValueDto> query = new ArrayList<>();
        for (DimensionValueOrgDto p : basicQuery) {
            if (p.getID() == null) {
                continue;
            }
            for (Map<String, Object> utemp : userRoleOrganization) {
                if (p.getID().equals(utemp.get("orgID"))) {
                    UserRoleDimensionValueDto userRoleDimensionValueDto = generateUserRoleDimensionValueDto(p, utemp);
                    userRoleDimensionValueDto.setDimensionValueID(p.getDimensionValueID());
                    userRoleDimensionValueDto.setDimensionID(p.getDimensionID());
                    query.add(userRoleDimensionValueDto);
                }
            }
        }
        return query;
    }

    @Override
    public List<UserOrgRoleDto> getDimensionUserRoleList(String parentDimensionID, String dimensionValueID) {
        List<DimensionValueOrgDto> orgList = getDimensionValueOrgDtoList().stream()
                .filter(s -> Objects.equals(parentDimensionID, s.getDimensionID())
                        && Objects.equals(dimensionValueID, s.getDimensionValueID()))
                .collect(Collectors.toList());
        List<UserDimensionValue> userDimensionValueList = findUserDimensionValueByDimensionRelatedID(parentDimensionID,
                dimensionValueID, null);
        List<UserDimensionValueOrg> userDimensionValueOrgList = getUserDimensionValueOrgList();
        List<UserOrganization> userOrganizationList = getUserOrganizationList().stream()
                .filter(s -> BooleanUtils.isTrue(s.getIsAccessible())).collect(Collectors.toList());
        // 机构的附加角色
        List<UserOrgRoleDto> userOrganizationRoleList = getUserOrganizationRoleList();

        // 获取原色角色列表
        List<UserOrgRoleDto> originalUserRoleList = getAllOriginalRole();

        // 维度的附加角色
        List<UserOrgRoleDto> userDimensionValueRoleList = getUserDimensionValueRoleList();

        // 维度上的机构
        List<UserRoleDimensionValueDto> dimensionOrgList = new ArrayList<>();
        for (DimensionValueOrgDto p : orgList) {
            for (UserDimensionValue q : userDimensionValueList) {
                if (Objects.equals(p.getDimensionID(), q.getDimensionID())
                        && Objects.equals(p.getDimensionValueID(), q.getDimensionValueID())) {
                    User u = findUserByStatusAndID(UserStatus.Active.value(), q.getUserID());
                    UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
                    if (u != null) {
                        userRoleDimensionValueDto.setUserName(u.getUserName());
                    }
                    userRoleDimensionValueDto.setID(q.getID());
                    userRoleDimensionValueDto.setHasOriginalRole(BooleanUtils.isTrue(q.getHasOriginalRole()));
                    userRoleDimensionValueDto.setIsAccessible(BooleanUtils.isTrue(q.getIsAccessible()));
                    userRoleDimensionValueDto.setUserID(q.getUserID());
                    userRoleDimensionValueDto.setOrganizationID(p.getOrganizationID());
                    userRoleDimensionValueDto.setOrganizationName(p.getOrganizationName());
                    userRoleDimensionValueDto.setDimensionID(p.getDimensionID());
                    userRoleDimensionValueDto.setDimensionName(p.getDimensionName());
                    userRoleDimensionValueDto.setDimensionValueID(p.getDimensionValueID());
                    userRoleDimensionValueDto.setDimensionValueName(p.getDimensionValue());
                    dimensionOrgList.add(userRoleDimensionValueDto);
                }
            }
        }
        List<UserOrgDto> orgNoAccessList = new ArrayList<>();
        List<UserOrgRoleDto> userOrgDtoList = new ArrayList<>();
        // 维度上的机构的用户
        for (UserRoleDimensionValueDto d : dimensionOrgList) {
            // 机构在维度上是否可以被继承,或者被访问
            UserDimensionValueOrg userDimensionValuerOrg = userDimensionValueOrgList.stream()
                    .filter(uvg -> Objects.equals(uvg.getUserDimensionValueID(), d.getID())
                            && Objects.equals(uvg.getOrganizationID(), d.getOrganizationID()))
                    .findFirst().orElse(null);
            // 如果没有设置值,默认可以继承
            boolean isHeritable = userDimensionValuerOrg == null
                    || BooleanUtils.isTrue(userDimensionValuerOrg.getIsHeritable());
            // 任何一个维度上不可访问,且机构继承这个维度,那么这个机构就不可访问
            if (!isHeritable) {
                continue;
            }
            // 用户继承了不可访问的,则这个机构不可访问
            if (isHeritable && !BooleanUtils.isTrue(d.getIsAccessible())
                    && orgNoAccessList.stream().noneMatch(s -> Objects.equals(s.getOrgID(), d.getOrganizationID())
                            && Objects.equals(s.getUserID(), d.getUserID()))) {
                UserOrgDto orgRoleInfo = new UserOrgDto();
                orgRoleInfo.setOrgID(d.getOrganizationID());
                orgRoleInfo.setUserID(d.getUserID());
                orgNoAccessList.add(orgRoleInfo);
                continue;
            }
            // 1.1 继承原始角色
            if (BooleanUtils.isTrue(d.getHasOriginalRole())) {
                // 原始角色
                List<UserOrgRoleDto> orignialUserRole = originalUserRoleList.stream()
                        .filter(s -> Objects.equals(s.getUserID(), d.getUserID())).collect(Collectors.toList());
                for (UserOrgRoleDto r : orignialUserRole) {
                    if (userOrgDtoList.stream()
                            .noneMatch(s -> Objects.equals(s.getOrgID(), d.getOrganizationID())
                                    && Objects.equals(s.getUserID(), d.getUserID())
                                    && Objects.equals(s.getRoleID(), r.getRoleID()))) {
                        userOrgDtoList.add(generateUserOrgRoleDto(d, r));
                    }
                }
            }
            List<UserOrgRoleDto> currentDimensionRoleList = userDimensionValueRoleList.stream()
                    .filter(s -> Objects.equals(s.getID(), d.getID())).collect(Collectors.toList());
            // 1.2 维度的附加角色
            for (UserOrgRoleDto r : currentDimensionRoleList) {
                if (userOrgDtoList.stream()
                        .noneMatch(s -> Objects.equals(s.getOrgID(), d.getOrganizationID())
                                && Objects.equals(s.getUserID(), d.getUserID())
                                && Objects.equals(s.getRoleID(), r.getRoleID()))) {
                    userOrgDtoList.add(generateUserOrgRoleDto(d, r));
                }
            }
        }
        // 移除没有访问权限的维度上的机构
        userOrgDtoList = userOrgDtoList.stream().filter(q -> orgNoAccessList.stream().noneMatch(
                es -> Objects.equals(es.getOrgID(), q.getOrgID()) && Objects.equals(es.getUserID(), q.getUserID())))
                .collect(Collectors.toList());
        // 机构上的用户角色
        List<UserRoleDimensionValueDto> userOrgList = new ArrayList<>();
        for (DimensionValueOrgDto p : orgList) {
            if (p == null || p.getOrganizationID() == null) {
                continue;
            }
            for (UserOrganization q : userOrganizationList) {
                if (p.getOrganizationID().equals(q.getOrganizationID())
                        && orgNoAccessList.stream().noneMatch(es -> Objects.equals(es.getOrgID(), p.getID())
                                && Objects.equals(es.getUserID(), q.getUserID()))) {
                    User u = findUserByStatusAndID(UserStatus.Active.value(), q.getUserID());
                    UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
                    if (u != null) {
                        userRoleDimensionValueDto.setUserName(u.getUserName());
                    }
                    userRoleDimensionValueDto.setID(q.getID());
                    userRoleDimensionValueDto.setHasOriginalRole(BooleanUtils.isTrue(q.getHasOriginalRole()));
                    userRoleDimensionValueDto.setIsAccessible(BooleanUtils.isTrue(q.getIsAccessible()));
                    userRoleDimensionValueDto.setUserID(q.getUserID());
                    userRoleDimensionValueDto.setOrganizationID(p.getOrganizationID());
                    userOrgList.add(userRoleDimensionValueDto);
                }
            }
        }

        for (UserRoleDimensionValueDto userOrg : userOrgList) {
            if (!BooleanUtils.isTrue(userOrg.getIsAccessible())) {
                continue;
            }
            if (BooleanUtils.isTrue(userOrg.getHasOriginalRole())) {
                // 原始角色
                List<UserOrgRoleDto> orignialUserRole = originalUserRoleList.stream()
                        .filter(s -> Objects.equals(s.getUserID(), userOrg.getUserID())).collect(Collectors.toList());
                for (UserOrgRoleDto r : orignialUserRole) {
                    if (userOrgDtoList.stream()
                            .noneMatch(s -> Objects.equals(s.getOrgID(), userOrg.getOrganizationID())
                                    && Objects.equals(s.getUserID(), userOrg.getUserID())
                                    && Objects.equals(s.getRoleID(), r.getRoleID()))) {
                        userOrgDtoList.add(generateUserOrgRoleDto(userOrg, r));
                    }
                }
            }
            List<UserOrgRoleDto> currentOrgRoleList = userOrganizationRoleList.stream()
                    .filter(s -> Objects.equals(s.getID(), userOrg.getID())).collect(Collectors.toList());
            // 1.2 机构的附加角色
            for (UserOrgRoleDto r : currentOrgRoleList) {
                if (userOrgDtoList.stream()
                        .noneMatch(s -> Objects.equals(s.getOrgID(), userOrg.getOrganizationID())
                                && Objects.equals(s.getUserID(), userOrg.getUserID())
                                && Objects.equals(s.getRoleID(), r.getRoleID()))) {
                    userOrgDtoList.add(generateUserOrgRoleDto(userOrg, r));
                }
            }
        }

        return userOrgDtoList;
    }

    private UserOrgRoleDto generateUserOrgRoleDto(UserRoleDimensionValueDto d, UserOrgRoleDto r) {
        UserOrgRoleDto userOrgDto = new UserOrgRoleDto();
        userOrgDto.setUserID(d.getUserID());
        userOrgDto.setUserName(d.getUserName());
        userOrgDto.setOrgID(d.getOrganizationID());
        userOrgDto.setRoleID(r.getRoleID());
        userOrgDto.setRoleName(r.getRoleName());
        return userOrgDto;
    }

    private List<UserDimensionValue> findUserDimensionValueByDimensionRelatedID(String parentDimensionID,
            String dimensionValueID, String userID) {
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        pwc.taxtech.atms.entity.UserDimensionValueExample.Criteria criteria = userDimensionValueExample
                .createCriteria();
        if (userID != null) {
            criteria.andUserIDEqualTo(userID);
        }
        criteria.andDimensionIDEqualTo(parentDimensionID);
        criteria.andDimensionValueIDEqualTo(dimensionValueID);
        return userDimensionValueMapper.selectByExample(userDimensionValueExample);
    }

    private List<UserOrgRoleDto> getAllOriginalRole() {
        return myUserMapper.selectUserOrgRoleDto();
    }

    private User findUserByStatusAndID(Integer status, String userID) {
        UserExample userExample = new UserExample();
        pwc.taxtech.atms.entity.UserExample.Criteria userCriteria = userExample.createCriteria();
        userCriteria.andStatusEqualTo(status);
        userCriteria.andIDEqualTo(userID);
        List<User> users = userMapper.selectByExample(userExample);
        return users.isEmpty() ? null : users.get(0);
    }

    /**
     * 添加事业部的值的权限(其他维度也一样) 可继承原始角色,可添加附加角色 原始角色写在标记HasOriginalRole
     * 附加角色写在角色关联表UserDimensionValueRole
     */
    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto updateUserRoleDimension(List<UserRoleDimensionValueDto> userRoleList) {
        logger.debug("UserRoleServiceImpl updateUserRoleDimension");
        if (userRoleList == null) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }
        OperationResultDto operationResultDto = new OperationResultDto<>();
        if (userRoleList.isEmpty()) {
            operationResultDto.setResult(true);
            return operationResultDto;
        }
        UserRoleDimensionValueDto first = userRoleList.get(0);
        // 删除用户维度的角色
        UserDimensionValue userDimensionValue = findUserDimensionValueByDimensionRelatedID(first.getDimensionID(),
                first.getDimensionValueID(), first.getUserID()).stream().findFirst().orElse(null);
        if (userDimensionValue == null) {
            throw new ApplicationException("UserDimensionValue cannot be found.");
        }
        UserDimensionValue old = CommonUtils.copyProperties(userDimensionValue, new UserDimensionValue());
        OrgCustomDto dimension = organizationService.getDimensionValueName(first.getDimensionID(),
                first.getDimensionValueID());
        if (dimension == null) {
            throw new ApplicationException("OrgCustomDto cannot be found.");
        }
        String dimensionName = dimension.getDimensionName();
        String dimensionValueName = dimension.getDimensionValueName();
        String operateUserName = getUserDtoByID(first.getUserID()).getUserName();
        // 删除某个维度值下面的所有附加角色
        List<UserDimensionValueRole> target = findUserDimensionValueRoleByUserDimensionValueID(
                userDimensionValue.getID());
        for (UserDimensionValueRole ou : target) {
            logger.debug("Start to delete userDimensionValueRole [ {} ]", ou.getID());
            userDimensionValueRoleMapper.deleteByPrimaryKey(ou.getID());
        }
        // 添加日志
        for (UserDimensionValueRole r : target) {
            Role role = roleMapper.selectByPrimaryKey(r.getRoleID());
            String roleName = role == null ? "" : role.getName();
            addOrDeleteDataAddLog(
                    dimensionName + CommonConstants.DashSignSeparator + dimensionValueName
                            + CommonConstants.DashSignSeparator + operateUserName + CommonConstants.DashSignSeparator
                            + roleName,
                    operateUserName, OperationModule.UserDimensionValueRole.value(), OperationAction.Delete.value(),
                    "");
        }
        // 更新用户维度角色
        userDimensionValue.setIsAccessible(BooleanUtils.isTrue(first.getIsAccessible()));
        userDimensionValue.setHasOriginalRole(BooleanUtils.isTrue(first.getHasOriginalRole()));
        logger.debug("Start to update userDimensionValue [ {} ]", userDimensionValue.getID());
        userDimensionValueMapper.updateByPrimaryKey(userDimensionValue);
        // 添加日志
        updateDataAddLog(old, userDimensionValue, OperationModule.BasicDataDimensionValue.value(),
                LogMessage.UpdateDimensionValue, operateUserName, dimensionName + CommonConstants.DashSignSeparator
                        + dimensionValueName + CommonConstants.DashSignSeparator + operateUserName,
                OperateLogType.OperationLogUser.value());
        // 添加选中的附加角色
        for (UserRoleDimensionValueDto item : userRoleList) {
            if (BooleanUtils.isTrue(item.getIsAdd())) {
                UserDimensionValueRole userRole = new UserDimensionValueRole();
                userRole.setID(CommonUtils.getUUID());
                userRole.setUserDimensionValueID(userDimensionValue.getID());
                userRole.setRoleID(item.getRoleID());
                logger.debug("Start to insert userDimensionValueRole [ {} ] with userDimensionValueID [ {} ]",
                        userRole.getID(), userDimensionValue.getID());
                userDimensionValueRoleMapper.insert(userRole);
                // 添加日志
                String roleName = getRoleDtoByID(item.getRoleID()).getName();
                addOrDeleteDataAddLog(
                        dimensionName + CommonConstants.DashSignSeparator + dimensionValueName
                                + CommonConstants.DashSignSeparator + operateUserName
                                + CommonConstants.DashSignSeparator + roleName,
                        operateUserName, OperationModule.UserDimensionValueRole.value(), OperationAction.New.value(),
                        "");
            }
        }
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    private List<UserDimensionValueRole> findUserDimensionValueRoleByUserDimensionValueID(String userDimensionValueID) {
        UserDimensionValueRoleExample userDimensionValueRoleExample = new UserDimensionValueRoleExample();
        userDimensionValueRoleExample.createCriteria().andUserDimensionValueIDEqualTo(userDimensionValueID);
        return userDimensionValueRoleMapper.selectByExample(userDimensionValueRoleExample);
    }

    private RoleDto getRoleDtoByID(String roleID) {
        Role query = roleMapper.selectByPrimaryKey(roleID);
        return query == null ? new RoleDto() : CommonUtils.copyProperties(query, new RoleDto());
    }

    /**
     * 机构用户权限编辑 添加删除原始角色 添加删除额外角色 机构上,修改可访问还是不可访问
     */
    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto updateUserRoleOrganization(List<UserRoleDimensionValueDto> userRoleList) {
        UserRoleDimensionValueDto first = userRoleList.stream().findFirst().orElse(null);
        OperationResultDto operationResultDto = new OperationResultDto();
        if (first == null) {
            operationResultDto.setResult(true);
            return operationResultDto;
        }
        String orgName = getOrgDtoByID(first.getOrganizationID()).getName();
        String operateUserName = getUserDtoByID(first.getUserID()).getUserName();
        // 编辑用户机构的角色
        UserOrganizationExample userOrganizationExample = new UserOrganizationExample();
        pwc.taxtech.atms.entity.UserOrganizationExample.Criteria criteria = userOrganizationExample.createCriteria();
        criteria.andUserIDEqualTo(first.getUserID());
        criteria.andOrganizationIDEqualTo(first.getOrganizationID());
        UserOrganization userOrganizationValue = userOrganizationMapper.selectByExample(userOrganizationExample)
                .stream().findFirst().orElse(null);
        String userOrgID = null;
        if (userOrganizationValue != null) {
            userOrgID = userOrganizationValue.getID();
            // 删除某个机构下面的所有附加角色
            UserOrganizationRoleExample userOrganizationRoleExample = new UserOrganizationRoleExample();
            userOrganizationRoleExample.createCriteria().andUserOrganizationIDEqualTo(userOrganizationValue.getID());
            List<UserOrganizationRole> target = userOrganizationRoleMapper.selectByExample(userOrganizationRoleExample);
            if (target != null && !target.isEmpty()) {
                for (UserOrganizationRole r : target) {
                    logger.debug("Start to delete UserOrganizationRole [ {} ]", r.getID());
                    userOrganizationRoleMapper.deleteByPrimaryKey(r.getID());

                    // 添加日志
                    Role role = roleMapper.selectByPrimaryKey(r.getRoleID());
                    String roleName = role == null ? "" : role.getName();
                    addOrDeleteDataAddLog(orgName + CommonConstants.DashSignSeparator + roleName, operateUserName,
                            OperationModule.UserOrganizationRole.value(), OperationAction.Delete.value(), "");
                }

            }
            UserOrganization old = CommonUtils.copyProperties(userOrganizationValue, new UserOrganization());
            // 更新用户机构角色
            userOrganizationValue.setIsAccessible(BooleanUtils.isTrue(first.getIsAccessible()));
            userOrganizationValue.setHasOriginalRole(BooleanUtils.isTrue(first.getHasOriginalRole()));
            logger.debug("Start to update userOrganizationValue [ {} ]", userOrganizationValue.getID());
            userOrganizationMapper.updateByPrimaryKey(userOrganizationValue);
            // 添加日志
            updateDataAddLog(old, userOrganizationValue, OperationModule.UserOrganization.value(), "", operateUserName,
                    orgName + CommonConstants.DashSignSeparator + operateUserName,
                    OperateLogType.OperationLogUser.value());

        } else {
            userOrgID = CommonUtils.getUUID();
            // 没有数据,则插入一条
            UserOrganization userRole = new UserOrganization();
            userRole.setID(userOrgID);
            userRole.setUserID(first.getUserID());
            userRole.setOrganizationID(first.getOrganizationID());
            userRole.setIsAccessible(BooleanUtils.isTrue(first.getIsAccessible()));
            userRole.setHasOriginalRole(BooleanUtils.isTrue(first.getHasOriginalRole()));
            logger.debug("Start to insert user organization [ {} ] with userID [ {} ]", userRole.getID(),
                    userRole.getUserID());
            userOrganizationMapper.insert(userRole);
            // 添加日志
            addOrDeleteDataAddLog(orgName + CommonConstants.DashSignSeparator + operateUserName, operateUserName,
                    OperationModule.UserOrganization.value(), OperationAction.New.value(), "");
        }
        // 添加选中的附加角色
        for (UserRoleDimensionValueDto item : userRoleList) {
            if (item.getRoleID() != null) {
                UserOrganizationRole userRole = new UserOrganizationRole();
                userRole.setID(CommonUtils.getUUID());
                userRole.setUserOrganizationID(userOrgID);
                userRole.setRoleID(item.getRoleID());
                logger.debug("Start to insert user organization role [ {} ] with roleID [ {} ]", userRole.getID(),
                        userRole.getRoleID());
                userOrganizationRoleMapper.insert(userRole);
                // 添加日志
                Role roleObject = roleMapper.selectByPrimaryKey(item.getRoleID());
                String roleName = roleObject == null ? "" : roleObject.getName();
                addOrDeleteDataAddLog(orgName + CommonConstants.DashSignSeparator + roleName, operateUserName,
                        OperationModule.UserOrganizationRole.value(), OperationAction.New.value(), "");
            }
        }
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    /**
     * 为维度删除权限用户
     */
    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto deleteUserRoleDimension(List<UserRoleDimensionValueDto> userRoleList) {
        logger.debug("UserRoleServiceImpl deleteUserRoleDimension");
        if (userRoleList.isEmpty()) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }

        for (UserRoleDimensionValueDto userRoleDimensionValue : userRoleList) {
            // 删除用户与维度的关联
            OperationResultDto operationResultDto = new OperationResultDto();
            UserDimensionValueExample userDimensioValueExample = new UserDimensionValueExample();
            userDimensioValueExample.createCriteria().andUserIDEqualTo(userRoleDimensionValue.getUserID())
                    .andDimensionIDEqualTo(userRoleDimensionValue.getDimensionID())
                    .andDimensionValueIDEqualTo(userRoleDimensionValue.getDimensionValueID());
            List<UserDimensionValue> userDimensionValueList = userDimensionValueMapper
                    .selectByExample(userDimensioValueExample);
            UserDimensionValue firstUserDimensionValue = userDimensionValueList.isEmpty() ? null
                    : userDimensionValueList.get(0);
            if (firstUserDimensionValue == null) {
                operationResultDto.setResult(true);
                return operationResultDto;
            }

            OrgCustomDto dimension = organizationService.getDimensionValueName(firstUserDimensionValue.getDimensionID(),
                    firstUserDimensionValue.getDimensionValueID());
            String dimensionName = dimension.getDimensionName();
            String dimensionValueName = dimension.getDimensionValueName();
            String operateUserName = getUserDtoByID(firstUserDimensionValue.getUserID()).getUserName();
            String userDimensionValueID = firstUserDimensionValue.getID();

            // 存在则删除 用户在这个维度
            deleteUserDimensionValueList(userDimensionValueList);

            // 添加日志
            userDimensionValueList.forEach(a -> {
                UpdateLogParams updateLogParams = new UpdateLogParams();
                updateLogParams.setOperateLogType(OperateLogType.OperationLogUser.value());
                updateLogParams.setOperationModule(OperationModule.UserDimensionValue.value());
                updateLogParams.setOperationContent(dimensionName + CommonConstants.DashSignSeparator + dimensionName
                        + CommonConstants.DashSignSeparator + operateUserName);
                updateLogParams.setOperationAction(OperationAction.Delete.value());
                updateLogParams.setOperationObject(operateUserName);
                operationLogService.addOrDeleteDataAddLog(updateLogParams);
            });

            // 删除附加维度
            UserDimensionValueRoleExample userDimensionValueRoleExample = new UserDimensionValueRoleExample();
            userDimensionValueRoleExample.createCriteria().andUserDimensionValueIDEqualTo(userDimensionValueID);
            List<UserDimensionValueRole> userDimensionValueRoleList = userDimensionValueRoleMapper
                    .selectByExample(userDimensionValueRoleExample);
            deleteUserDimensionValueRoleList(userDimensionValueRoleList);

            // 添加日志
            userDimensionValueRoleList.forEach(a -> {
                String roleName = getRoleDtoByID(a.getRoleID()).getName();
                UpdateLogParams updateLogParams = new UpdateLogParams();
                updateLogParams.setOperateLogType(OperateLogType.OperationLogUser.value());
                updateLogParams.setOperationModule(OperationModule.UserDimensionValueRole.value());
                updateLogParams.setOperationContent(dimensionName + CommonConstants.DashSignSeparator
                        + dimensionValueName + CommonConstants.DashSignSeparator + operateUserName
                        + CommonConstants.DashSignSeparator + roleName);
                updateLogParams.setOperationAction(OperationAction.Delete.value());
                updateLogParams.setOperationObject(operateUserName);
                operationLogService.addOrDeleteDataAddLog(updateLogParams);
            });
        }
        OperationResultDto operationResultDto = new OperationResultDto();
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    private void deleteUserDimensionValueRoleList(List<UserDimensionValueRole> userDimensionValueRoleList) {
        if (!userDimensionValueRoleList.isEmpty()) {
            userDimensionValueRoleList.forEach(a -> {
                UserDimensionValueRoleExample example = new UserDimensionValueRoleExample();
                example.createCriteria().andUserDimensionValueIDEqualTo(a.getUserDimensionValueID());
                userDimensionValueRoleMapper.deleteByExample(example);
            });
        }
    }

    private void deleteUserDimensionValueList(List<UserDimensionValue> userDimensionValueList) {
        if (!userDimensionValueList.isEmpty()) {
            userDimensionValueList.forEach(a -> {
                UserDimensionValueExample example = new UserDimensionValueExample();
                example.createCriteria().andUserIDEqualTo(a.getUserID()).andDimensionIDEqualTo(a.getDimensionID())
                        .andDimensionValueIDEqualTo(a.getDimensionValueID());
                userDimensionValueMapper.deleteByExample(example);
            });
        }
    }

    // 给维度(事业部)添加用户
    @Override
    public OperationResultDto<?> updateUserRoleForDimension(List<UserRoleDimensionValueDto> userRoleList) {
        logger.debug("UserRoleServiceImpl updateUserRoleForDimension");
        if (userRoleList.isEmpty()) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }

        for (UserRoleDimensionValueDto item : userRoleList) {
            UserDimensionValueExample userDimensioValueExample = new UserDimensionValueExample();
            userDimensioValueExample.createCriteria().andUserIDEqualTo(item.getUserID())
                    .andDimensionIDEqualTo(item.getDimensionID())
                    .andDimensionValueIDEqualTo(item.getDimensionValueID());
            List<UserDimensionValue> userDimensionValueList = userDimensionValueMapper
                    .selectByExample(userDimensioValueExample);
            // 如果已经存在,则不再添加了
            if (userDimensionValueList.isEmpty()) {
                UserDimensionValue userDimensionValue = new UserDimensionValue();
                userDimensionValue.setID(CommonUtils.getUUID());
                userDimensionValue.setDimensionID(item.getDimensionID());
                userDimensionValue.setDimensionValueID(item.getDimensionValueID());
                userDimensionValue.setUserID(item.getUserID());
                boolean isAccessible = BooleanUtils.isTrue(item.getIsAccessible());
                userDimensionValue.setIsAccessible(isAccessible);
                boolean hasOriginalRole = BooleanUtils.isTrue(item.getHasOriginalRole());
                userDimensionValue.setHasOriginalRole(hasOriginalRole);
                userDimensionValueMapper.insert(userDimensionValue);
                logger.debug("userDimensionValue to insert: {}", userDimensionValue.toString());

                // 添加日志
                OrgCustomDto dimension = organizationService.getDimensionValueName(item.getDimensionID(),
                        item.getDimensionValueID());
                String dimensionName = dimension.getDimensionName();
                String dimensionValueName = dimension.getDimensionValueName();
                String operateUserName = getUserDtoByID(item.getUserID()).getUserName();

                UpdateLogParams updateLogParams = new UpdateLogParams();
                updateLogParams.setComment(LogMessage.AddUserForDimensionValue);
                updateLogParams.setOperateLogType(OperateLogType.OperationLogUser.value());
                updateLogParams.setOperationModule(OperationModule.UserDimensionValue.value());
                updateLogParams.setOperationContent(dimensionName + CommonConstants.DashSignSeparator
                        + dimensionValueName + CommonConstants.DashSignSeparator + operateUserName);
                updateLogParams.setOperationAction(OperationAction.New.value());
                updateLogParams.setOperationObject(operateUserName);
                operationLogService.addOrDeleteDataAddLog(updateLogParams);
            }
        }
        OperationResultDto<?> operationResultDto = new OperationResultDto<>();
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto updateUserRoleForOrg(List<UserRoleDimensionValueDto> userRoleList) {
        if (userRoleList == null) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }
        for (UserRoleDimensionValueDto item : userRoleList) {
            List<UserOrganization> query = userService.findUserOrganizationByUserIDAndOrganizationID(item.getUserID(),
                    item.getOrganizationID());
            User user = userMapper.selectByPrimaryKey(item.getUserID());
            Organization organization = organizationMapper.selectByPrimaryKey(item.getOrganizationID());
            String operateUserName = user == null ? "" : user.getUserName();
            String orgName = organization == null ? "" : organization.getName();
            // 如果已经存在,则不再添加了
            if (query == null || query.isEmpty()) {
                UserOrganization ur = new UserOrganization();
                ur.setID(CommonUtils.getUUID());
                ur.setOrganizationID(item.getOrganizationID());
                ur.setUserID(item.getUserID());
                ur.setIsAccessible(BooleanUtils.isTrue(item.getIsAccessible()));
                ur.setHasOriginalRole(BooleanUtils.isTrue(item.getHasOriginalRole()));
                logger.debug("Start to insert UserOrganization [ {} ]", ur.getID());
                userOrganizationMapper.insert(ur);
                // 添加日志
                addOrDeleteDataAddLog(orgName + CommonConstants.DashSignSeparator + operateUserName, operateUserName,
                        OperationModule.UserOrganization.value(), OperationAction.New.value(),
                        LogMessage.AddUserForOrganization);
            } else {
                UserOrganization first = query.stream().findFirst().orElse(null);
                if (first != null) {
                    if (BooleanUtils.isFalse(first.getIsAccessible())) {
                        first.setIsAccessible(CommonConstants.IsAccessible);
                    }
                    if (BooleanUtils.isFalse(first.getHasOriginalRole())) {
                        first.setHasOriginalRole(CommonConstants.HasOriginalRole);
                    }
                    logger.debug("Start to update UserOrganization [ {} ]", first.getID());
                    userOrganizationMapper.updateByPrimaryKey(first);
                    // 添加日志
                    addOrDeleteDataAddLog(orgName + CommonConstants.DashSignSeparator + operateUserName,
                            operateUserName, OperationModule.UserOrganization.value(), OperationAction.New.value(),
                            LogMessage.AddUserForOrganization);
                }
            }
        }
        OperationResultDto operationResultDto = new OperationResultDto();
        operationResultDto.setResult(true);
        return operationResultDto;
    }

    /**
     * 在某个机构下面,删除用户(特殊权限和继承的权限),如果是特殊权限,直接删除权限机构的数据, 如果是继承维度的权限,将继承的维度设置为不可继承
     */
    @SuppressWarnings("rawtypes")
    @Override
    public OperationResultDto deleteUserRoleByOrgID(UserOrgDto userDto) {
        logger.debug("enter UserRoleServiceImpl");
        if (userDto == null) {
            throw new ApplicationException(CommonConstants.JSONNULLOBJECT);
        }

        OperationResultDto result = null;

        // 删除用户与机构上的角色
        UserOrganizationExample example = new UserOrganizationExample();
        example.createCriteria().andOrganizationIDEqualTo(userDto.getOrgID()).andUserIDEqualTo(userDto.getUserID());
        List<UserOrganization> target = userOrganizationMapper.selectByExample(example);
        UserOrganization first = target.stream().findFirst().orElse(null);
        if (first == null) {
            result = new OperationResultDto<>();
            result.setResult(true);
            return result;
        }

        target.forEach(a -> {
            userOrganizationMapper.deleteByPrimaryKey(a.getID());
        });

        String userOrganizationID = first.getID();
        // 机构上的附加角色
        UserOrganizationRoleExample userOrganizationRoleExample = new UserOrganizationRoleExample();
        userOrganizationRoleExample.createCriteria().andUserOrganizationIDEqualTo(userOrganizationID);
        List<UserOrganizationRole> userOrganizationRole = userOrganizationRoleMapper
                .selectByExample(userOrganizationRoleExample);

        userOrganizationRole.forEach(a -> {
            userOrganizationRoleMapper.deleteByPrimaryKey(a.getID());
        });

        // 用户在所有机构继承维度上,设置成不可继承
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        userDimensionValueExample.createCriteria().andUserIDEqualTo(userDto.getUserID());
        List<UserDimensionValue> userDimensionValue = userDimensionValueMapper
                .selectByExample(userDimensionValueExample);
        userDimensionValue.forEach(a -> {
            // 机构上继承的维度
            UserDimensionValueOrgExample userDimensionValueOrgExample = new UserDimensionValueOrgExample();
            userDimensionValueOrgExample.createCriteria().andOrganizationIDEqualTo(userOrganizationID)
                    .andUserDimensionValueIDEqualTo(a.getID());
            List<UserDimensionValueOrg> inheritDimensionList = userDimensionValueOrgMapper
                    .selectByExample(userDimensionValueOrgExample);
            inheritDimensionList.forEach(b -> {
                b.setIsHeritable(CommonConstants.DEACTIVE_STATUS);// 设置为不可继承
                userDimensionValueOrgMapper.updateByPrimaryKey(b);
            });
        });

        result = new OperationResultDto<>();
        result.setResult(true);
        return result;
    }

    @Override
    public UserDto GetUserByUserName(UserDto userParam) {
        return userService.getUserByDto(userParam);
    }
}