package com.cool.store.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.dto.StoreNameDTO;
import com.cool.store.dao.store.StoreMasterSignerInfoDAO;
import com.cool.store.dto.store.AuthStoreUserDTO;
import com.cool.store.dao.EnterpriseUserDAO;
import com.cool.store.dao.EnterpriseUserRoleDao;
import com.cool.store.dao.StoreDao;
import com.cool.store.dao.SysRoleDao;
import com.cool.store.dto.StoreDTO;
import com.cool.store.dto.store.StoreAreaDTO;
import com.cool.store.dto.store.StoreUserDTO;
import com.cool.store.dto.store.StoreUserPositionDTO;
import com.cool.store.entity.*;
import com.cool.store.entity.store.StoreMasterSignerInfoDO;
import com.cool.store.enums.*;
import com.cool.store.exception.ServiceException;
import com.cool.store.mapper.*;
import com.cool.store.response.MiniShopsResponse;
import com.cool.store.service.StoreService;
import com.cool.store.service.UserAuthMappingService;
import com.cool.store.utils.poi.constant.Constants;
import com.cool.store.vo.SysRoleVO;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
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.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author suzhuhong
 * @Date 2025/5/13 9:56
 * @Version 1.0
 */
@Service
@Slf4j
public class StoreServiceImpl implements StoreService {

    @Resource
    StoreDao storeDao;
    @Resource
    private EnterpriseUserDAO enterpriseUserDAO;
    @Resource
    private EnterpriseUserRoleDao enterpriseUserRoleDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private UserAuthMappingService userAuthMappingService;
    @Resource
    private RegionMapper regionMapper;
    @Resource
    SysRoleMapper sysRoleMapper;
    @Resource
    StoreMapper storeMapper;
    @Resource
    UserAuthMappingMapper userAuthMappingMapper;
    @Resource
    EnterpriseUserMapper enterpriseUserMapper;
    @Resource
    EnterpriseUserGroupMappingMapper enterpriseUserGroupMappingMapper;
    @Resource
    StoreMasterSignerInfoDAO storeMasterSignerInfoDAO;

    @Override
    public PageInfo<StoreDTO> getStoreExtendFieldInfo(Integer pageSize, Integer pageNum) {
        if (pageSize>200){
            throw new ServiceException(ErrorCodeEnum.ERROR_MESSAGE,"单次最多获取200条门店数据");
        }
        PageHelper.startPage(pageNum,pageSize);
        List<StoreDO> list = storeDao.list(null);
        PageInfo info = new PageInfo<>(list);
        if (CollectionUtils.isEmpty(list)){
            return  info;
        }
        //使用regionId与branch 合并的集合
        Set<Long> regionIds = list.stream()
                .filter(Objects::nonNull)
                .flatMap(store -> Stream.of(store.getBranch(), store.getRegionId()))
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        List<RegionDO> regionList = regionMapper.getByIds(new ArrayList<>(regionIds));
        Map<Long, String> regionNameMap = regionList.stream().collect(Collectors.toMap(RegionDO::getId, RegionDO::getName));

        List<StoreDTO> storeDTOS = processStores(list, regionNameMap);
        info.setList(storeDTOS);
        return info;
    }

    @Override
    public PageInfo<StoreNameDTO> getIotStoreList(Integer pageNum, Integer pageSize) {
        if (pageSize > 200) {
            throw new ServiceException(ErrorCodeEnum.ERROR_MESSAGE, "单次最多获取200条门店数据");
        }
        PageHelper.startPage(pageNum, pageSize);
        List<StoreDO> list = storeDao.list(1);
        PageInfo info = new PageInfo<>(list);
        if (CollectionUtils.isEmpty(list)){
            return info;
        }
        List<StoreNameDTO> result = list.stream().map(v -> new StoreNameDTO(v.getStoreName(), v.getStoreNum())).collect(Collectors.toList());
        info.setList(result);
        return info;
    }

    @Override
    public PageInfo<MiniShopsResponse> getStoreListByMobile(String mobile,Integer pageNum,Integer pageSize,String storeName,String storeNum) {
        //根据手机号查询 标品userId
        EnterpriseUserDO enterpriseUserDO = enterpriseUserDAO.selectByMobile(mobile);
        List<String> regionIds = new ArrayList<>();
        if (Objects.nonNull(enterpriseUserDO)){
            //获取用户职位
            List<Long> userRoleIds = enterpriseUserRoleDao.getUserRoleIds(enterpriseUserDO.getUserId());
            //查询职位详情，筛选掉店外职位
            List<SysRoleDO> roleIds = sysRoleDao.selectRoleByRoleIds(userRoleIds);
            List<SysRoleDO> sysRoleDOS = roleIds.stream().filter(role -> "store_inside".equals(role.getPositionType())
                    ||UserRoleEnum.SUPERVISION.getCode().equals(role.getId())
                    ||UserRoleEnum.HEAD_OF_DIVISION.getCode().equals(role.getId())
                    ||UserRoleEnum.REGION_MANAGER.getCode().equals(role.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(sysRoleDOS)){
                //获取用户管辖区域
                List<UserAuthMappingDO> userAuthMapping = userAuthMappingService.listUserAuthMappingByUserId(enterpriseUserDO.getUserId());
                if (CollectionUtils.isNotEmpty(userAuthMapping)){
                    regionIds.addAll(userAuthMapping.stream().map(UserAuthMappingDO::getMappingId).collect(Collectors.toList()));
                }
            }
        }
        PageHelper.startPage(pageNum,pageSize);
        List<MiniShopsResponse> list = storeDao.getSubStoreByRegionIdsAndMobile(regionIds,mobile,storeName,storeNum);
        return  new PageInfo<>(list);
    }

    @Override
    public List<StoreUserPositionDTO> getStoreUser(List<String> storeCodeList) {
        if (CollectionUtils.isNotEmpty(storeCodeList)&&storeCodeList.size()>=100){
            throw new ServiceException(ErrorCodeEnum.ERROR_MESSAGE,"单次最多获取100条门店数据");
        }
        List<StoreDO> list = storeDao.getStoreNumByStoreCodes(storeCodeList);
        if (CollectionUtils.isEmpty(list)){
            return  new ArrayList<>();
        }
        List<String> storeIds = CollStreamUtil.toList(list, StoreDO::getStoreId);
        Map<String, StoreMasterSignerInfoDO> signerMap = storeMasterSignerInfoDAO.getSignerMapByStoreIds(storeIds);
        List<StoreUserPositionDTO> result = new ArrayList<>();
        list.forEach(x->{
            StoreUserPositionDTO storeUserPositionDTO = new StoreUserPositionDTO();
            List<StoreUserDTO> storeUserPosition = this.getStoreUserPositionDTO(x.getStoreId());
            Map<String, List<StoreUserDTO>> storeUserDTOMap = ListUtils.emptyIfNull(storeUserPosition).stream().collect(Collectors.groupingBy(k -> k.getUserId()));
            storeUserPositionDTO.setStoreId(x.getStoreId());
            storeUserPositionDTO.setStoreName(x.getStoreName());
            storeUserPositionDTO.setShopCode(x.getStoreNum());
            storeUserPositionDTO.setStoreCode(x.getStoreNum());
            List<StoreUserDTO> userList = Lists.newArrayList();
            for (String userId : storeUserDTOMap.keySet()) {
                List<StoreUserDTO> singleUserDTOList = storeUserDTOMap.get(userId);
                if(CollectionUtils.isEmpty(singleUserDTOList)){
                    continue;
                }
                StoreUserDTO storeUserDTO = singleUserDTOList.get(0);
                List<String> positionNameList = ListUtils.emptyIfNull(singleUserDTOList)
                        .stream().map(StoreUserDTO::getPositionName).collect(Collectors.toList());
                storeUserDTO.setPositionName(String.join(Constants.COMMA, positionNameList));
                userList.add(storeUserDTO);
            }
            StoreMasterSignerInfoDO signerInfoDO = signerMap.get(x.getStoreId());
            if (Objects.nonNull(signerInfoDO)) {
                Set<String> mobiles = CollStreamUtil.toSet(userList, StoreUserDTO::getMobile);
                if (StringUtils.isNotBlank(signerInfoDO.getSigner1Mobile()) && mobiles.add(signerInfoDO.getSigner1Mobile())) {
                    userList.add(new StoreUserDTO(signerInfoDO.getSigner1Name(), signerInfoDO.getSigner1Mobile()));
                }
                if (StringUtils.isNotBlank(signerInfoDO.getSigner2Mobile()) && mobiles.add(signerInfoDO.getSigner2Mobile())) {
                    userList.add(new StoreUserDTO(signerInfoDO.getSigner2Name(), signerInfoDO.getSigner2Mobile()));
                }
            }
            storeUserPositionDTO.setUserList(userList);
            result.add(storeUserPositionDTO);
        });
        return result;
    }



    private List<StoreUserDTO> getStoreUserPositionDTO(String storeId){
        if (StrUtil.isBlank(storeId)) {
            throw new ServiceException(ErrorCodeEnum.PARAMS_VALIDATE_ERROR.getCode(), "请选择门店后查询");
        }
        List<AuthStoreUserDTO> authStoreUserDTOList = this.authStoreUser(
                Collections.singletonList(storeId), "store_inside");

        if (CollectionUtils.isEmpty(authStoreUserDTOList)) {
            return new ArrayList<>();
        }
        List<String> userIdList = ListUtils.emptyIfNull(authStoreUserDTOList)
                .stream()
                .map(AuthStoreUserDTO::getUserIdList)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(userIdList)) {
            return new ArrayList<>();
        }
        List<StoreUserDTO> result = sysRoleMapper.userAndPositionList( userIdList, null, "store_inside");
        return result;
    }



    @Override
    public List<AuthStoreUserDTO> getStorePositionUserList( List<String> storeIds,
                                                           List<String> positionIds,
                                                           List<String> nodePersonList,
                                                           List<String> groupIdList,
                                                           List<String> regionIdList) {
        log.info("StoreServiceImpl getStorePositionUserList param storeIds:{},positionIds:{},nodePersonList:{},groupIdList:{},regionIdList:{}",
                JSONObject.toJSONString(storeIds),
                JSONObject.toJSONString(positionIds), JSONObject.toJSONString(nodePersonList),
                JSONObject.toJSONString(groupIdList), JSONObject.toJSONString(regionIdList));
        List<AuthStoreUserDTO> authStoreUsers = this.authStoreUser(storeIds, null);
        if (CollUtil.isEmpty(authStoreUsers)) {
            return new ArrayList<>();
        }
        List<String> allUserIds = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(positionIds)) {
            List<String> userIds = sysRoleMapper.getPositionUserIds(positionIds);
            allUserIds.addAll(userIds);
        }
        if (CollectionUtils.isNotEmpty(groupIdList)) {
            List<String> groupUserIdList = enterpriseUserGroupMappingMapper.getUserIdsByGroupIdList(groupIdList);
            if (CollectionUtils.isNotEmpty(groupUserIdList)) {
                allUserIds.addAll(groupUserIdList);
            }
        }
        if (CollectionUtils.isNotEmpty(regionIdList)) {
            List<String> regionUserIdList = enterpriseUserMapper.getUserIdsByRegionIdList(regionIdList);
            if (CollectionUtils.isNotEmpty(regionUserIdList)) {
                allUserIds.addAll(regionUserIdList);
            }
        }
        if (CollectionUtils.isNotEmpty(nodePersonList)) {
            allUserIds.addAll(nodePersonList);
        }
        List<String> finalAllUserIds = allUserIds;
        authStoreUsers.forEach(f -> f.getUserIdList().retainAll(finalAllUserIds));
        if (CollectionUtils.isNotEmpty(authStoreUsers)) {
            authStoreUsers = authStoreUsers.stream().distinct().collect(Collectors.toList());
        }
        return authStoreUsers;
    }



    @Override
    public List<AuthStoreUserDTO> authStoreUser(List<String> storeIdList, String positionType) {
        List<AuthStoreUserDTO> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(storeIdList)) {
            return result;
        }
        //将拥有管理员角色、角色属性为全企业数据的人查询出来
        List<SysRoleVO> roleUserByRoleId = sysRoleMapper.getRoleUserByRoleEnum(Role.MASTER.getRoleEnum(),positionType);
        List<SysRoleVO> roleUserByRoleAuth = sysRoleMapper.getRoleUserByRoleAuth(AuthRoleEnum.ALL.getCode(),positionType);
        //组合出拥有所有门店信息的人
        List<String>  allStoreUserIdList = getAllStoreUserIdList(roleUserByRoleId, roleUserByRoleAuth);
        //查询出有门店权限配置的的人员
        //   1.将门店区域切分出门店所属于的区域ID
        //   2.将配置了区域的人 查询出来
        //   3.将配置了门店的人 查询出来
        List<StoreAreaDTO> storeAreaList = storeMapper.getStoreAreaList(storeIdList);
        if (CollectionUtils.isEmpty(storeAreaList)) {
            return Collections.emptyList();
        }

        List<String> fullAreaIdList = ListUtils.emptyIfNull(storeAreaList)
                .stream()
                .map(StoreAreaDTO::getAreaIdList)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());


        List<String> lastAreaIdList = ListUtils.emptyIfNull(storeAreaList)
                .stream()
                .map(StoreAreaDTO::getAreaId)
                .distinct()
                .collect(Collectors.toList());

        //除不包含子区域的可视化范围的区域配置。
        List<UserAuthMappingDO> regionUserAuthMappingList = userAuthMappingMapper.listUserAuthMappingByAuth(
                UserAuthMappingTypeEnum.REGION.getCode(), fullAreaIdList, positionType, AuthRoleEnum.NOT_INCLUDE_SUBORDINATE.getCode());
        //不包含子区域的的直属连接门店的区域下的配置(会重复一些选择了上面数据)
        List<UserAuthMappingDO> notIncludeRegionUserAuthMappingList = userAuthMappingMapper.listUserAuthMappingByAuth(
                UserAuthMappingTypeEnum.REGION.getCode(), lastAreaIdList, positionType, null);
        //配置了门店的的配置
        List<UserAuthMappingDO> storeUserAuthMappingList = userAuthMappingMapper.listUserAuthMappingByMappingList(
                storeIdList, UserAuthMappingTypeEnum.STORE.getCode());
        return ListUtils.emptyIfNull(storeAreaList)
                .stream()
                .map(data -> mapAuthStoreUserDTO(regionUserAuthMappingList, allStoreUserIdList, storeUserAuthMappingList, notIncludeRegionUserAuthMappingList, data))
                .collect(Collectors.toList());
    }

    private List<String> getAllStoreUserIdList(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 AuthStoreUserDTO mapAuthStoreUserDTO(
            List<UserAuthMappingDO> regionUserAuthMappingList,
            List<String> allStoreUserIdList,
            List<UserAuthMappingDO> storeUserAuthMappingList,
            List<UserAuthMappingDO> notIncludeRegionUserAuthMappingList,
            StoreAreaDTO data) {

        //组装全部的人员信息
        List<String> authStoreIdList = new ArrayList<>();
        AuthStoreUserDTO authStoreUserDTO = new AuthStoreUserDTO();
        authStoreUserDTO.setStoreId(data.getStoreId());
        authStoreUserDTO.setStoreName(data.getStoreName());
        //组装拥有所有门店信息的人
        if (CollectionUtils.isNotEmpty(allStoreUserIdList)) {
            authStoreIdList.addAll(allStoreUserIdList);
        }
        //组装配置了区域权限的人(除了不包含子区域可视化范围)
        List<String> storeAreaIdList = data.getAreaIdList();
        List<String> regionUserIdList = ListUtils.emptyIfNull(regionUserAuthMappingList).stream()
                .filter(area -> storeAreaIdList.contains(area.getMappingId()))
                .map(UserAuthMappingDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(regionUserIdList)) {
            authStoreIdList.addAll(regionUserIdList);
        }
        //组装配置了区域权限的人(不包含子区域可视化范围)
        List<String> notIncludeRegionUserIdList = ListUtils.emptyIfNull(notIncludeRegionUserAuthMappingList).stream()
                .filter(area -> StringUtils.equals(data.getAreaId(), area.getMappingId()))
                .map(UserAuthMappingDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(notIncludeRegionUserIdList)) {
            authStoreIdList.addAll(notIncludeRegionUserIdList);
        }
        //组装配置了门店权限的人
        List<String> storeUserIdList = ListUtils.emptyIfNull(storeUserAuthMappingList).stream()
                .filter(store -> StringUtils.equals(store.getMappingId(), data.getStoreId()))
                .map(UserAuthMappingDO::getUserId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(storeUserIdList)) {
            authStoreIdList.addAll(storeUserIdList);
        }

        //去除重复数据
        List<String> distinctUserIdList = ListUtils.emptyIfNull(authStoreIdList).stream()
                .distinct()
                .collect(Collectors.toList());
        authStoreUserDTO.setUserIdList(distinctUserIdList);
        return authStoreUserDTO;
    }


    public static List<StoreDTO> processStores(List<StoreDO> stores,Map<Long, String> regionMap) {
        // 处理每个门店
        return stores.stream().map(store -> {
            StoreDTO dto = BeanUtil.toBean(store, StoreDTO.class);
            dto.setStoreCode(store.getStoreNum());
            dto.setStoreAvatar(store.getAvatar());
            dto.setStoreType(StoreTypeEnum.getMessage(store.getStoreType()));
            dto.setJoinMode(JoinModeEnum.getByCode(store.getJoinModel()));
            dto.setBrand(FranchiseBrandEnum.getDescByCode(store.getJoinBrand()));
            dto.setOrderMiniProgramName(store.getMiniProgramOrderStoreName());
            dto.setStatus(StoreStatusEnum.getName(store.getStoreStatus()));
            if (store.getRegionId() != null){
                dto.setManagerSupervisionName(regionMap.get(store.getRegionId()));
            }
            if (store.getBranch()!=null){
                dto.setBranchName(regionMap.get(store.getBranch()));
            }
            return dto;
        }).collect(Collectors.toList());
    }

}
