package com.cool.store.service.impl;

import cn.hutool.core.util.StrUtil;
import com.cool.store.constants.CommonConstants;
import com.cool.store.dao.EnterpriseUserDAO;
import com.cool.store.dao.RegionAreaConfigDao;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
import com.cool.store.exception.ServiceException;
import com.cool.store.mapper.RegionMapper;
import com.cool.store.mapper.SysRoleMapper;
import com.cool.store.mapper.UserAuthMappingMapper;
import com.cool.store.service.UserAuthMappingService;
import com.cool.store.utils.RedisConstantUtil;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.poi.constant.Constants;
import com.cool.store.vo.SysRoleVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * describe:
 *
 * @author wxp
 * @date 2020/11/11
 */
@Service
@Slf4j
public class UserAuthMappingServiceImpl implements UserAuthMappingService {

    @Resource
    private UserAuthMappingMapper userAuthMappingMapper;

    @Resource
    private RegionAreaConfigDao regionAreaConfigDao;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private RegionMapper regionMapper;

    @Resource
    private EnterpriseUserDAO enterpriseUserDAO;

    @Resource
    private RedisUtilPool redisUtilPool;

    @Autowired
    private RedisConstantUtil redisConstantUtil;

    @Value("${spring.profiles.active}")
    private String active;

    @Override
    public List<UserAuthMappingDO> listUserAuthMappingByUserId(String userId) {
        if (StringUtils.isBlank(userId)) {
            return Lists.newArrayList();
        }
        return userAuthMappingMapper.listUserAuthMappingByUserId(userId);
    }

    @Override
    public List<String> getAuthRegionIdAndSubRegionIdByUserId(String userId) {
        List<UserAuthMappingDO> userAuthMapping = listUserAuthMappingByUserId(userId);
        if (CollectionUtils.isEmpty(userAuthMapping)) {
            return Lists.newArrayList();
        }
        List<String> regionIds = userAuthMapping.stream().map(UserAuthMappingDO::getMappingId).collect(Collectors.toList());
        List<String> subRegionIds = regionMapper.getSubRegionIdsByRegionIds(regionIds);
        if (CollectionUtils.isNotEmpty(subRegionIds)) {
            regionIds.addAll(subRegionIds);
        }
        return regionIds;
    }

    @Override
    public List<String> getAuthStoreIdAndSubRegionIdByUserId(String userId) {
        List<UserAuthMappingDO> userAuthMapping = listUserAuthMappingByUserId(userId);
        if (CollectionUtils.isEmpty(userAuthMapping)) {
            return Lists.newArrayList();
        }
        List<String> regionIds = userAuthMapping.stream().map(UserAuthMappingDO::getMappingId).collect(Collectors.toList());
        List<String> subRegionIds = regionMapper.getStoreIdsByRegionIds(regionIds);
        if (CollectionUtils.isNotEmpty(subRegionIds)) {
            regionIds.addAll(subRegionIds);
        }
        return regionIds;
    }

    /**
     * 提供 根据职位 意向区域  查  对应人的接口  同时返回人名字
     *
     * @param userRoleEnum
     * @param wantShopAreaId
     * @return
     */
    @Override
    public EnterpriseUserDO getUserByRoleEnumAndWantShopAreaId(UserRoleEnum userRoleEnum, Long wantShopAreaId) {
        log.info("getUserByRoleEnumAndAreaId：{}，wantShopAreaId：{}", userRoleEnum, wantShopAreaId);
        if (Objects.isNull(userRoleEnum) || Objects.isNull(wantShopAreaId)) {
            return null;
        }
        String investmentManagerKey = redisConstantUtil.getInvestmentManagerKey(wantShopAreaId, userRoleEnum.getCode());
        String suitableUserId = redisUtilPool.rpopStr(investmentManagerKey);
        if (StringUtils.isNotBlank(suitableUserId)) {
            EnterpriseUserDO userDO = enterpriseUserDAO.getUserInfoById(suitableUserId);
            return userDO;
        }
        Long warRegionId = regionAreaConfigDao.getByWantShopAreaId(wantShopAreaId);
        if (warRegionId == null) {
            return fillDefaultUser(userRoleEnum);
        }
        // 查找有战区权限的人
        List<String> authWarRegionUserIdList = authWarRegionUser(warRegionId);
        if (CollectionUtils.isEmpty(authWarRegionUserIdList)) {
            return fillDefaultUser(userRoleEnum);
        }
        Long roleId = userRoleEnum.getCode();
        List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
        if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
            return fillDefaultUser(userRoleEnum);
        }
        authWarRegionUserIdList.retainAll(hasRoleUserIdList);
        if (CollectionUtils.isEmpty(authWarRegionUserIdList)) {
            return fillDefaultUser(userRoleEnum);
        }
        authWarRegionUserIdList = authWarRegionUserIdList.stream()
                .sorted((a, b) -> b.compareTo(a))
                .collect(Collectors.toList());
        redisUtilPool.listPushTail(investmentManagerKey, authWarRegionUserIdList.toArray(new String[authWarRegionUserIdList.size()]));
        suitableUserId = redisUtilPool.rpopStr(investmentManagerKey);
        EnterpriseUserDO userDO = enterpriseUserDAO.getUserInfoById(suitableUserId);
        return userDO;
    }

    /**
     * 获取有区域权限和职位 的人
     *
     * @param userRoleEnum
     * @param regionId
     * @return
     */
    @Override
    public EnterpriseUserDO getUserByRoleEnumAndRegionId(UserRoleEnum userRoleEnum, Long regionId) {
        // 查找有区域权限的人
        List<String> authRegionUserIdList = authWarRegionUser(regionId);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        Long roleId = userRoleEnum.getCode();
        List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
        if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
            return null;
        }
        authRegionUserIdList.retainAll(hasRoleUserIdList);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        if (CollectionUtils.isNotEmpty(authRegionUserIdList)) {
            EnterpriseUserDO userDO = enterpriseUserDAO.getUserInfoById(authRegionUserIdList.get(0));
            return userDO;
        }
        return null;
    }

    @Override
    public List<EnterpriseUserDO> getAllUserByRoleEnumAndRegionId(UserRoleEnum userRoleEnum, Long regionId) {
        // 查找有区域权限的人
        List<String> authRegionUserIdList = authWarRegionUser(regionId);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        Long roleId = userRoleEnum.getCode();
        List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
        if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
            return null;
        }
        authRegionUserIdList.retainAll(hasRoleUserIdList);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        if (CollectionUtils.isNotEmpty(authRegionUserIdList)) {
            List<EnterpriseUserDO> userInfoByUserIds = enterpriseUserDAO.getUserInfoByUserIds(authRegionUserIdList);
            return userInfoByUserIds;
        }
        return null;
    }

    @Override
    public List<EnterpriseUserDO> getUserByRoleEnumAndRegionIdList(UserRoleEnum userRoleEnum, Long regionId) {
        // 查找有区域权限的人
        List<String> authRegionUserIdList = authWarRegionUser(regionId);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        Long roleId = userRoleEnum.getCode();
        List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
        if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
            return null;
        }
        authRegionUserIdList.retainAll(hasRoleUserIdList);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return null;
        }
        if (CollectionUtils.isNotEmpty(authRegionUserIdList)) {
            return enterpriseUserDAO.getUserInfoByUserIds(authRegionUserIdList);

        }
        return null;
    }

    private EnterpriseUserDO fillDefaultUser(UserRoleEnum userRoleEnum) {
        String defaultJobnumber = getDefaultJobnumber(userRoleEnum);
        // 如果找不到督导，则分配给默认的督导
        if (UserRoleEnum.SUPERVISION.equals(userRoleEnum)) {
            EnterpriseUserDO defaultUser = enterpriseUserDAO.getUserInfoByJobnumber(defaultJobnumber);
            if (defaultUser == null) {
                defaultUser = enterpriseUserDAO.getUserInfoById(defaultJobnumber);
            }
            return defaultUser;
        } else if (UserRoleEnum.SELECT_SITE_COMMISSIONER.equals(userRoleEnum)) {
            // 如果找不到选址专员，则分配给默认的选址经理
            EnterpriseUserDO defaultUser = enterpriseUserDAO.getUserInfoByJobnumber(defaultJobnumber);
            if (defaultUser == null) {
                defaultUser = enterpriseUserDAO.getUserInfoById(defaultJobnumber);
            }
            return defaultUser;
        }
        return null;
    }

    @Override
    public Map<String, List<String>> getUserIdByRoleIdAndRegionId(List<String> roleIds, Long regionId) {
        if (CollectionUtils.isEmpty(roleIds) || Objects.isNull(regionId)) {
            return Maps.newHashMap();
        }
        RegionDO regionDO = regionMapper.getByRegionId(regionId);
        if (regionDO == null) {
            throw new ServiceException(ErrorCodeEnum.REGION_NOT_EXIST);
        }
        // 查找有区域权限的人
        List<String> authRegionUserIdList = authWarRegionUser(regionId);
        if (CollectionUtils.isEmpty(authRegionUserIdList)) {
            return Maps.newHashMap();
        }
        List<Long> roleIdList = roleIds.stream().map(a -> Long.valueOf(a)).collect(Collectors.toList());
        List<EnterpriseUserRole> enterpriseUserRoleList = sysRoleMapper.getUserIdListByRoleIdList(roleIdList);
        enterpriseUserRoleList = ListUtils.emptyIfNull(enterpriseUserRoleList).stream().filter(o -> authRegionUserIdList.contains(o.getUserId())).collect(Collectors.toList());
        Map<String, List<String>> enterpriseUserRoleMap = ListUtils.emptyIfNull(enterpriseUserRoleList).stream().collect(Collectors.groupingBy(EnterpriseUserRole::getRoleId, Collectors.mapping(k -> k.getUserId(), Collectors.toList())));
        return enterpriseUserRoleMap;
    }

    /**
     * 根据 人  查 这个人管辖区域  对应的意向区域省市code   团队线索
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> listWantShopAreaIdByUserId(String userId) {
        //如果在缓存中存在，从缓存中去取
        String userWantAreaListKey = redisConstantUtil.getUserWantAreaListKey(userId);
        List<String> userWantAreaList = redisUtilPool.listGetAll(userWantAreaListKey);
        if (CollectionUtils.isNotEmpty(userWantAreaList)) {
            List<Long> authRegionIdListFromCache = userWantAreaList.stream().map(regionId -> Long.valueOf(regionId)).collect(Collectors.toList());
            return authRegionIdListFromCache;
        }
        List<UserAuthMappingDO> userAuthList = this.listUserAuthMappingByUserId(userId);
        List<String> authRegionIds = ListUtils.emptyIfNull(userAuthList)
                .stream().map(UserAuthMappingDO::getMappingId)
                .collect(Collectors.toList());
        List<Long> authRegionIdList = ListUtils.emptyIfNull(authRegionIds).stream().map(regionId -> Long.valueOf(regionId)).collect(Collectors.toList());
        List<RegionAreaConfigDO> regionAreaConfigDOList = regionAreaConfigDao.listAreaByRegionIdList(authRegionIdList);
        List<Long> wantShopAreaIdList = ListUtils.emptyIfNull(regionAreaConfigDOList)
                .stream().map(RegionAreaConfigDO::getWantShopAreaId)
                .collect(Collectors.toList());
        List<String> wantShopAreaIdStrList = wantShopAreaIdList.stream().map(areaId -> String.valueOf(areaId)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(wantShopAreaIdStrList)) {
            redisUtilPool.listPushTail(userWantAreaListKey, wantShopAreaIdStrList.toArray(new String[wantShopAreaIdList.size()]));
            redisUtilPool.expire(userWantAreaListKey, 5 * 60);
        }
        return wantShopAreaIdList;
    }

    @Override
    public String getShopManagerUserId() {
        Boolean isOnline = active.equals(CommonConstants.HD_ENV) || active.equals(CommonConstants.ONLINE_ENV);
        return  isOnline ? CommonConstants.DEAULT_SHOP_MANAGER_USER_ID_ONLINE : CommonConstants.DEAULT_SHOP_MANAGER_USER_ID_TEST;
    }

    // 查找有战区权限的人
    public List<String> authWarRegionUser(Long warRegionId) {
        List<String> result = new ArrayList<>();
        if (Objects.isNull(warRegionId)) {
            return result;
        }
        RegionDO regionDO = regionMapper.getByRegionId(warRegionId);
        if (regionDO == null) {
            throw new ServiceException(ErrorCodeEnum.REGION_NOT_EXIST);
        }
        //将拥有管理员角色、角色属性为全企业数据的人查询出来
        List<SysRoleVO> roleUserByRoleId = sysRoleMapper.getRoleUserByRoleEnum(Role.MASTER.getRoleEnum(), null);
        List<SysRoleVO> roleUserByRoleAuth = sysRoleMapper.getRoleUserByRoleAuth(AuthRoleEnum.ALL.getCode(), null);
        //组合出拥有所有门店信息的人
        List<String> allWarRegionUserIdList = getAllWarRegionAuthUserIdList(roleUserByRoleId, roleUserByRoleAuth);
        //查询出有门店权限配置的的人员
        //   1.将门店区域切分出门店所属于的区域ID
        //   2.将配置了区域的人 查询出来
        List<String> fullAreaIdList = StrUtil.splitTrim(regionDO.getRegionPath(), "/");
        List<String> lastAreaIdList = Collections.singletonList(String.valueOf(regionDO.getId()));
        //除不包含子区域的可视化范围的区域配置。
        List<UserAuthMappingDO> regionUserAuthMappingList =
                userAuthMappingMapper.listUserAuthMappingByAuth(UserAuthMappingTypeEnum.REGION.getCode(), fullAreaIdList, null, AuthRoleEnum.NOT_INCLUDE_SUBORDINATE.getCode());
        //不包含子区域的的直属连接门店的区域下的配置(会重复一些选择了上面数据)
        List<UserAuthMappingDO> notIncludeRegionUserAuthMappingList =
                userAuthMappingMapper.listUserAuthMappingByAuth(UserAuthMappingTypeEnum.REGION.getCode(), lastAreaIdList, null, null);
        List<String> authWarRegionUserIdList = mapAuthStoreUserDTO(regionUserAuthMappingList, allWarRegionUserIdList, notIncludeRegionUserAuthMappingList);
        return authWarRegionUserIdList;
    }


    private List<String> getAllWarRegionAuthUserIdList(List<SysRoleVO> roleUserByRoleId, List<SysRoleVO> roleUserByRoleAuth) {
        List<String> allUserIdList = new ArrayList<>();
        List<String> masterUserList = ListUtils.emptyIfNull(roleUserByRoleId).stream()
                .map(SysRoleVO::getEnterpriseDOs)
                .flatMap(Collection::stream)
                .map(EnterpriseUserDO::getUserId)
                .collect(Collectors.toList());
        List<String> roleAllUserList = ListUtils.emptyIfNull(roleUserByRoleAuth).stream()
                .map(SysRoleVO::getEnterpriseDOs)
                .flatMap(Collection::stream)
                .map(EnterpriseUserDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(masterUserList)) {
            allUserIdList.addAll(masterUserList);
        }
        if (CollectionUtils.isNotEmpty(roleAllUserList)) {
            allUserIdList.addAll(roleAllUserList);
        }
        return ListUtils.emptyIfNull(allUserIdList)
                .stream()
                .distinct()
                .collect(Collectors.toList());

    }


    private List<String> mapAuthStoreUserDTO(
            List<UserAuthMappingDO> regionUserAuthMappingList,
            List<String> allWarRegionUserIdList,
            List<UserAuthMappingDO> notIncludeRegionUserAuthMappingList) {
        //组装全部的人员信息
        List<String> authUserIdList = new ArrayList<>();
        //组装拥有所有门店信息的人
        if (CollectionUtils.isNotEmpty(allWarRegionUserIdList)) {
            authUserIdList.addAll(allWarRegionUserIdList);
        }
        //组装配置了区域权限的人(除了不包含子区域可视化范围)
        List<String> regionUserIdList = ListUtils.emptyIfNull(regionUserAuthMappingList).stream()
                .map(UserAuthMappingDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(regionUserIdList)) {
            authUserIdList.addAll(regionUserIdList);
        }
        //组装配置了区域权限的人(不包含子区域可视化范围)
        List<String> notIncludeRegionUserIdList = ListUtils.emptyIfNull(notIncludeRegionUserAuthMappingList).stream()
                .map(UserAuthMappingDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(notIncludeRegionUserIdList)) {
            authUserIdList.addAll(notIncludeRegionUserIdList);
        }
        //去除重复数据
        List<String> distinctUserIdList = ListUtils.emptyIfNull(authUserIdList).stream()
                .distinct()
                .collect(Collectors.toList());
        return distinctUserIdList;
    }

    private String getDefaultJobnumber(UserRoleEnum userRoleEnum) {
        Boolean isOnline = active.equals(CommonConstants.HD_ENV) || active.equals(CommonConstants.ONLINE_ENV);
        // 如果找不到招商专员，则分配给默认的招商经理
        if (UserRoleEnum.INVESTMENT_COMMISSIONER.equals(userRoleEnum)|| UserRoleEnum.STRONG_INVESTMENT_COMMISSIONER.equals(userRoleEnum)) {
            return  isOnline ? CommonConstants.DEAULT_INVESTMENT_JOBNUMBER_ONLINE : CommonConstants.DEAULT_INVESTMENT_JOBNUMBER_TEST;
        } else if (UserRoleEnum.SELECT_SITE_COMMISSIONER.equals(userRoleEnum)) {
            // 如果找不到选址专员，则分配给默认的选址经理
            return  isOnline ? CommonConstants.DEAULT_SELECT_SITE_MANAGER_ONLINE : CommonConstants.DEAULT_SELECT_SITE_MANAGER_TEST;
        }
        return null;
    }


    @Override
    public EnterpriseUserDO hierarchicalSearch(UserRoleEnum supervision, Long regionId) {
        //督导
        EnterpriseUserDO supervisionUser = getUserByRoleEnumAndRegionId(UserRoleEnum.SUPERVISION, regionId);
        RegionDO smallRegion = regionMapper.getByRegionId(regionId);
        List<String> regionIds = extractNumbers(smallRegion.getRegionPath());
        List<RegionDO> regionByRegionIds = regionMapper.getRegionByRegionIds(regionIds);
        List<RegionDO> fightRegions = regionByRegionIds.stream().filter(item -> Constants.TWO_STRING.equals(item.getThirdRegionType())).collect(Collectors.toList());
        List<RegionDO> bigRegions = regionByRegionIds.stream().filter(item -> Constants.ONE_STRING.equals(item.getThirdRegionType())).collect(Collectors.toList());
        RegionDO fightRegion = new RegionDO();
        RegionDO bigRegion = new RegionDO();
        if (CollectionUtils.isNotEmpty(fightRegions)){
            fightRegion = fightRegions.get(0);
        }
        if (CollectionUtils.isNotEmpty(bigRegions)){
            bigRegion = bigRegions.get(0);
        }
        try {
            if (Objects.isNull(supervisionUser)){
                //战区经理
                EnterpriseUserDO theaterManager = getUserByRoleEnumAndRegionId(UserRoleEnum.THEATER_MANAGER, fightRegion.getId());
                if (Objects.isNull(theaterManager)){
                    //大区总
                    EnterpriseUserDO regionManager = getUserByRoleEnumAndRegionId(UserRoleEnum.REGION_MANAGER, bigRegion.getId());
                    if (Objects.isNull(regionManager)){
                        EnterpriseUserDO userInfoByJobnumber = enterpriseUserDAO.getUserInfoByJobnumber(Constants.WANG_LEI_JOB_NUMBER);
                        if (Objects.isNull(userInfoByJobnumber)){
                            throw new ServiceException("找不到督导");
                        }else {
                            return userInfoByJobnumber;
                        }
                    }
                }
                return theaterManager;
            }
        }catch (Exception e){
            log.error("hierarchicalSearch errorMessage:{}",e.getMessage());
            throw new ServiceException(ErrorCodeEnum.UNKNOWN);
        }

        return supervisionUser;
    }

    private List<String> extractNumbers(String regionPath) {
        List<String> regionIds = new ArrayList<>();
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(regionPath);

        while (matcher.find()) {
            regionIds.add(String.valueOf(matcher.group()));
        }

        return regionIds;
    }


}
